Validation on a Many-to-Many Through model ( unique_together=[a, b, c=1] )
I have the following models (simplified example): class Book(models.Model): users = models.ManyToManyField(User, through=Permission) class Permission(models.Model): user = models.ForeignKey(User) role = models.ForeignKey(Group) active = models.BooleanField() book = models.ForeignKey(Book) What I need is that for a Book instance there cannot be more than one User of with the same Role and Active. So this is allowed: Alice, Admin, False (not active), BookA Dick, Admin, True (active), BookA Chris, Editor, False (not active), BookA Matt, Editor, False (not active), BookA But this is not allowed: Alice, Admin, True (active), BookA Dick, Admin, True (active), BookA Now this cannot be done using unique_together, because it only counts when active is True. I've tried to write a custom clean/ validate_unique method (like how I have done here: http://stackoverflow.com/questions/3052427/validation-on-manytomanyfield-before-save-in-models-py/3266169#3266169). But it seems that when you save a Book and it runs the validation on each Permission, the already validated Permission instances aren't saved until they've all been validated. This makes sense, because you don't want them to be saved in case something doesn't validate. Could anyone tell me if there is a way to perform the validation described above? P.S. I could imagine using the savepoint feature (http:// docs.djangoproject.com/en/1.2/topics/db/transactions/), but I only really want to consider that as a last resort. Note! I first posted this question on StackOverflow. I received a response but the answer wouldn't work for me. Please have a look at the response to avoid repeating the answer: http://stackoverflow.com/questions/3759687/ -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: Admin Model Validation on ManyToMany Field
Thanks very much for your reply! I got it working now. At first I couldn't get my head around how it would work using the clean of the intermediary model. But after a night's sleep it made sense to me. In the Admin my Permission model (the users field) is an inline of Application and when I put the validation on Permission it also automatically works in the Application Admin. So now I have: admin.py class PermissionInline(admin.TabularInline): form = PermissionForm model = Permission extra = 3 forms.py class PermissionForm(forms.ModelForm): class Meta: model = Permission def clean(self): cleaned_data = self.cleaned_data user = cleaned_data['user'] role = cleaned_data['role'] if role.id != 1: folder = cleaned_data['application'].folder if len(filter(lambda x:x in user.profile.company.all(),folder.company.all())) > 0: # this is an intersection raise forms.ValidationError("One of the users of this Application works for one of the Repository's organisations!") return cleaned_data And this works! On Jul 14, 5:16 pm, jaymzcd <jaym...@googlemail.com> wrote: > Hi Heleen, > > I think this is because your running the users through an intermediate > model. That changes the way you need to work with the M2M data. You > should be working on the Permission model/objects instead. If you > check out the M2M docs for models via an intermediate: > > http://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-o... > > You'll see the example is pretty much what you have only with Group > instead of Application. > > "The only way to create this type of relationship is to create > instances of the intermediate model. Unlike normal many-to-many > fields, you can't use add, create, or assignment (i.e., > beatles.members = [...]) to create relationships:" > > jaymz > > On Jul 14, 2:32 pm, Heleen <heleen...@gmail.com> wrote: > > > Thank you for your reply. > > > Yes I have selected a user and folder. > > I believe ManyToMany fields are always optional (hence many to many). > > So my users and company fields are optional, but my folder field > > isn't. > > When I add a new Application in the Admin I do specify a folder and > > users (if I don't I would at least get a 'Required field' error for > > the folder field). > > I've tested the method above (clean function) with another model that > > has a manytomany field, and it does exactly the same thing, even when > > I really do fill in the data. In fact, if I delibirately throw an > > error and look in the debug info I can see the ManyToMany field data > > being present in the POST data, just like I can when I do the same > > thing with the above models. > > > Btw, I just noticed a typo in my Folder model description above, > > that's not the issue as it's correct in my original model. > > > On Jul 14, 2:02 pm, Nuno Maltez <nuno.li...@gmail.com> wrote: > > > > Hi, > > > > Just a guess: have you actually selected a user and a folder when > > > submitting the form? I think only valid field are present on the > > > cleaned_data dict, and your users and folder fields are not optional > > > (blank=True, null=True). > > > > hth, > > > nuno > > > > On Tue, Jul 13, 2010 at 1:45 PM, Heleen <heleen...@gmail.com> wrote: > > > > Hello, > > > > > I have the following classes: > > > > class Application(models.Model): > > > > users = models.ManyToManyField(User, through='Permission') > > > > folder = models.ForeignKey(Folder) > > > > > class Folder(models.Model): > > > > company = models.ManyToManyField(Compnay) > > > > > class UserProfile(models.Model): > > > > user = models.OneToOneField(User, related_name='profile') > > > > company = models.ManyToManyField(Company) > > > > > Now when I save application, I would like to check if the users do not > > > > belong to the application's folder's companies. > > > > I have posed this question before and someone came up with the > > > > following sollution: > > > > forms.py: > > > > class ApplicationForm(ModelForm): > > > > class Meta: > > > > model = Application > > > > > def clean(self): > > > > cleaned_data = self.cleaned_data > > > > users = cleaned_data['users'] > > > > folder = cleaned_data['folder'] > > > > if > > > > users.filter(profile__company__in=folder.company.all()).count()
Re: Admin Model Validation on ManyToMany Field
Thank you for your reply. Yes I have selected a user and folder. I believe ManyToMany fields are always optional (hence many to many). So my users and company fields are optional, but my folder field isn't. When I add a new Application in the Admin I do specify a folder and users (if I don't I would at least get a 'Required field' error for the folder field). I've tested the method above (clean function) with another model that has a manytomany field, and it does exactly the same thing, even when I really do fill in the data. In fact, if I delibirately throw an error and look in the debug info I can see the ManyToMany field data being present in the POST data, just like I can when I do the same thing with the above models. Btw, I just noticed a typo in my Folder model description above, that's not the issue as it's correct in my original model. On Jul 14, 2:02 pm, Nuno Maltez <nuno.li...@gmail.com> wrote: > Hi, > > Just a guess: have you actually selected a user and a folder when > submitting the form? I think only valid field are present on the > cleaned_data dict, and your users and folder fields are not optional > (blank=True, null=True). > > hth, > nuno > > On Tue, Jul 13, 2010 at 1:45 PM, Heleen <heleen...@gmail.com> wrote: > > Hello, > > > I have the following classes: > > class Application(models.Model): > > users = models.ManyToManyField(User, through='Permission') > > folder = models.ForeignKey(Folder) > > > class Folder(models.Model): > > company = models.ManyToManyField(Compnay) > > > class UserProfile(models.Model): > > user = models.OneToOneField(User, related_name='profile') > > company = models.ManyToManyField(Company) > > > Now when I save application, I would like to check if the users do not > > belong to the application's folder's companies. > > I have posed this question before and someone came up with the > > following sollution: > > forms.py: > > class ApplicationForm(ModelForm): > > class Meta: > > model = Application > > > def clean(self): > > cleaned_data = self.cleaned_data > > users = cleaned_data['users'] > > folder = cleaned_data['folder'] > > if > > users.filter(profile__company__in=folder.company.all()).count() > 0: > > raise forms.ValidationError('One of the users of this > > Application works in one of the Folder companies!') > > return cleaned_data > > > admin.py > > class ApplicationAdmin(ModelAdmin): > > form = ApplicationForm > > > This seems like right the way to go about this. The problem is that > > neither the users nor folder fields are in the cleaned_data and I get > > a keyerror when it hits the users = cleaned_data['users'] line. > > > I was hoping that someone here could explain to me why these > > manytomany fields don't show up in cleaned_data and that someone could > > possibly give me a sollution to my problem. > > > Thanks! > > Heleen > > > -- > > You received this message because you are subscribed to the Google Groups > > "Django users" group. > > To post to this group, send email to django-us...@googlegroups.com. > > To unsubscribe from this group, send email to > > django-users+unsubscr...@googlegroups.com. > > For more options, visit this group > > athttp://groups.google.com/group/django-users?hl=en. > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Admin Model Validation on ManyToMany Field
Hello, I have the following classes: class Application(models.Model): users = models.ManyToManyField(User, through='Permission') folder = models.ForeignKey(Folder) class Folder(models.Model): company = models.ManyToManyField(Compnay) class UserProfile(models.Model): user = models.OneToOneField(User, related_name='profile') company = models.ManyToManyField(Company) Now when I save application, I would like to check if the users do not belong to the application's folder's companies. I have posed this question before and someone came up with the following sollution: forms.py: class ApplicationForm(ModelForm): class Meta: model = Application def clean(self): cleaned_data = self.cleaned_data users = cleaned_data['users'] folder = cleaned_data['folder'] if users.filter(profile__company__in=folder.company.all()).count() > 0: raise forms.ValidationError('One of the users of this Application works in one of the Folder companies!') return cleaned_data admin.py class ApplicationAdmin(ModelAdmin): form = ApplicationForm This seems like right the way to go about this. The problem is that neither the users nor folder fields are in the cleaned_data and I get a keyerror when it hits the users = cleaned_data['users'] line. I was hoping that someone here could explain to me why these manytomany fields don't show up in cleaned_data and that someone could possibly give me a sollution to my problem. Thanks! Heleen -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: commit=False in Model save?
Today I'm a bit more awake than when I replied yesterday and I realized that you're talking about views here. What I mean however is that I would like to do validation in the model class' save function in models.py. I have tried to use this method on my save function though, but it just gives me the following error: Transaction managed block ended with pending COMMIT/ROLLBACK I don't think it should be pending. My save function will eventually commit or rollback and the error occurs in both cases. So either this method doesn't work when used on a model class' save function, or because it's not a view function, something else needs to happen as well that I don't know of (in case of a rollback the function might for example need to return an error of some kind). I've also come across the problem that the 'through' table of my ManyToManyField is not updated before commit. I call super(Model, self).save(*args, **kwargs) at the start of def save(*args, **kwargs):, but I get an empty list when after super-save I try to retrieve the linked through instances, because they simply do not exist yet. Could anyone tell me if what I'm doing is the right way of approaching it and how it should be done? Thanks! -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: commit=False in Model save?
Thanks to the 'unknown' user for the reply. This is probably what I'm looking for. I think I have had a glance at it while searching the Django Docs but I don't think I fully understood it. I do now and will give it a go tomorrow morning! -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: commit=False in Model save?
Someone e-mailed me a reply, and I thought I'd make it public before I reply. What you could do is use manual transaction management and do something like: @transaction.commit_manually def my_view(request): ... try: my_form.save() except MyFormException: # thrown when validation fails, etc. transaction.rollback() finally: transaction.commit() That should allow you to create the PKs and then get out of there if there's a problem. On Jun 15, 9:23 am, Heleen <heleen...@gmail.com> wrote: > Hello, > > I have a situation where I would like to do some validation on a many- > to-many field in a model before it is saved. When the validation fails > the model should not be saved and result in an appropriate error. > However to be able to do anything with a many-to-many field the > primary key of the model should be available, therefore it seems that > the model should be saved first. > > In Forms there is the option to save with commit=False, but I could > not find anything similar to this for the Models save function. > Also, using a pre-save signal would not work, because the model is not > saved yet. A post-save signal doesn't work either because then the > model gets saved even in the cases that it shouldn't. Rewriting the > save function would be the best option, but because I cannot 'pre'- > save with commit=False this doesn't work either. > > Could anyone tell me if there is such a function to achieve what I > need or if there is a better way of doing this? > Thanks very much! > Heleen -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
commit=False in Model save?
Hello, I have a situation where I would like to do some validation on a many- to-many field in a model before it is saved. When the validation fails the model should not be saved and result in an appropriate error. However to be able to do anything with a many-to-many field the primary key of the model should be available, therefore it seems that the model should be saved first. In Forms there is the option to save with commit=False, but I could not find anything similar to this for the Models save function. Also, using a pre-save signal would not work, because the model is not saved yet. A post-save signal doesn't work either because then the model gets saved even in the cases that it shouldn't. Rewriting the save function would be the best option, but because I cannot 'pre'- save with commit=False this doesn't work either. Could anyone tell me if there is such a function to achieve what I need or if there is a better way of doing this? Thanks very much! Heleen -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: send_mail not sending e-mail in view, but does send e-mail in shell
Thanks for your help, I figured out in the end what was causing the problem. Because there was a problem with Spawning crashing and not properly restarting when using more than 0 threads, we had set the number of threads to 0. However this appeared to cause the e-mail sending problem. We set the number of threads back to 4 and that was solved, then we did sudo easy_install -U MySQL-python Spawning eventlet setuptools. And after restarting the spawning script, all problems were solved. It now sends e-mail and restarts correctly. I have to say that nothing showed up in any log, so that's why it took us so long to figure this out. Thanks again for your help though. On Feb 16, 7:19 pm, creecode <creec...@gmail.com> wrote: > Hello Heleen, > > I don't have any specific solutions for you. In several of my > projects I have views that do deliver email without issue. > > A couple of things come to mind. Have you checked that the arguments > passed to send_mail in your view are correct? Is it possible that > there is some kind of permission problem? Something like the Nginx > process isn't allowed to send email? > > It might help us to help you if you could let us see the relevant code > in question and any tracebacks if there is an error. > > On Feb 15, 1:09 pm, Heleen <heleen...@gmail.com> wrote: > > > When I try to send an e-mail using > > send_mail() trough the Django website (so via a view function), it > > does not deliver the e-mail. However when on the same server I use > > 'python manage.py shell' it does deliver the e-mail. > > Toodle-lo... > creecode -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
send_mail not sending e-mail in view, but does send e-mail in shell
Hi, I hope this question hasn't been asked before, if so please link me to the answer (I couldn't find it). I have the following problem. When I try to send an e-mail using send_mail() trough the Django website (so via a view function), it does not deliver the e-mail. However when on the same server I use 'python manage.py shell' it does deliver the e-mail. I'm using Postfix (and earlier I tried Exim as well) to handle e-mails. When I send the e-mail using the shell it shows up in the logs. When I try sending it through the website it does not show up in any log. Postfix really is set-up correctly and I am also certain that the code in the view is correct. Sending e-mail does work on a similar server which has an earlier version of Python and Django. I'm running Django 1.1 on a Debian server with Python 2.5.2 running spawning with Nginx. I use the following startup script: #!/bin/sh PROJNAME=website PROJDIR=/var/www/heleen/website PORT=9001 cd ${PROJDIR}/../ /usr/bin/spawn --factory=spawning.django_factory.config_factory $ {PROJNAME}.settings --port=$PORT --threads=0 --processes=1 --access- log-file=/var/log/django/${PROJNAME} & Is there anyone who has any idea what I'm missing? Thank very much in advance for your help! Heleen -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.