0

I have a Django model that uploads photos to a user's account. The upload model uses a Django auth user as a foreign key. I needed to ensure that each user could only upload 20 photos total and I wanted to do this at the model level so even the admin could not upload more. I got that working in a way but it broke my admin form validation. If I choose a related user, everything goes perfectly. It stops me from uploading more than 20 photos. But if I don't choose a user it gives me RelatedObjectDoesNotExist error. I am including my code and traceback here. Help would be appreciated.

My models.py

def photo_count(self):
    theModel = self.__class__
    refModel = theModel.objects.filter(user=self.user)
    picCount = refModel.count()
    if picCount ==20:
        print(picCount)
        raise ValidationError ("You have already uploaded 20 photos. Delete some to upload more.")


class StarPhotos(models.Model):

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    PHOTO_CATEGORY = (
    ('HS', "Head Shot"),
    ('WP', "Western Party Wear"),
    ('IP', "Indian Party Wear"),
    ('SW', "Swim Wear"),
    ('CW', "Casual Wear"),
    )
    category = models.CharField(max_length=2, choices=PHOTO_CATEGORY, default='CW')
    # This FileField should preferaby be changed to ImageField with pillow installed.
    photos = models.FileField(max_length=200, upload_to='images/',)

    def __str__(self):
        return "Images for {0}".format(self.user)


    def clean(self):
        photo_count(self)


    class Meta:
        verbose_name_plural = "Star Photos"

Traceback

Request Method: POST
Request URL: http://127.0.0.1:8000/admin/castar/starphotos/add/

Django Version: 1.11.1
Python Version: 3.6.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'castar.apps.CastarConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "D:\websites\powah\lib\site-packages\django\core\handlers\exception.py" in inner
  41.             response = get_response(request)

File "D:\websites\powah\lib\site-packages\django\core\handlers\base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "D:\websites\powah\lib\site-packages\django\core\handlers\base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "D:\websites\powah\lib\site-packages\django\contrib\admin\options.py" in wrapper
  551.                 return self.admin_site.admin_view(view)(*args, **kwargs)

File "D:\websites\powah\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "D:\websites\powah\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)

File "D:\websites\powah\lib\site-packages\django\contrib\admin\sites.py" in inner
  224.             return view(request, *args, **kwargs)

File "D:\websites\powah\lib\site-packages\django\contrib\admin\options.py" in add_view
  1508.         return self.changeform_view(request, None, form_url, extra_context)

File "D:\websites\powah\lib\site-packages\django\utils\decorators.py" in _wrapper
  67.             return bound_func(*args, **kwargs)

File "D:\websites\powah\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "D:\websites\powah\lib\site-packages\django\utils\decorators.py" in bound_func
  63.                 return func.__get__(self, type(self))(*args2, **kwargs2)

File "D:\websites\powah\lib\site-packages\django\contrib\admin\options.py" in changeform_view
  1408.             return self._changeform_view(request, object_id, form_url, extra_context)

File "D:\websites\powah\lib\site-packages\django\contrib\admin\options.py" in _changeform_view
  1440.             if form.is_valid():

File "D:\websites\powah\lib\site-packages\django\forms\forms.py" in is_valid
  183.         return self.is_bound and not self.errors

File "D:\websites\powah\lib\site-packages\django\forms\forms.py" in errors
  175.             self.full_clean()

File "D:\websites\powah\lib\site-packages\django\forms\forms.py" in full_clean
  386.         self._post_clean()

File "D:\websites\powah\lib\site-packages\django\forms\models.py" in _post_clean
  396.             self.instance.full_clean(exclude=exclude, validate_unique=False)

File "D:\websites\powah\lib\site-packages\django\db\models\base.py" in full_clean
  1233.             self.clean()

File "D:\websites\powah\src\castar\models.py" in clean
  75.         photo_count(self)

File "D:\websites\powah\src\castar\models.py" in photo_count
  49.     refModel = theModel.objects.filter(user=self.user)

File "D:\websites\powah\lib\site-packages\django\db\models\fields\related_descriptors.py" in __get__
  194.                 "%s has no %s." % (self.field.model.__name__, self.field.name)

Exception Type: RelatedObjectDoesNotExist at /admin/castar/starphotos/add/
Exception Value: StarPhotos has no user.
  • Why would you want not to choose a user? Every photo must have an user, mustn't it? – doru May 18 '17 at 21:10
  • @doru I know what you mean. But I don't feel nice ruining admin form validation. Without my custom validation the admin form validaiton works and I want it to work exactly the same with my custom validation or at least fail gracefully. – chewinggumking May 18 '17 at 21:22
  • You could add `blank=True` to your `user` field: `user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)` – doru May 18 '17 at 21:25
  • Currently, your model requires a user to be selected. By not choosing a user, it raises an error saying a user must be selected. The model is doing it's job properly. To avoid having to choose a user, you can add `blank=True` in the field. – jape May 18 '17 at 21:26
  • @jape Is there anyway I can catch the model form exception and use that as a condition to run my validation? example pseudo code. If there is modelform exception do not run custom validation else run custom custom form validation. – chewinggumking May 18 '17 at 21:38
  • This answer may help you: http://stackoverflow.com/questions/6333738/django-how-to-specify-which-field-a-validation-fails-on – jape May 18 '17 at 23:24
  • @jape I DID IT!. I put the validation in admins.py and put the code in there so my admin forms wouldn't get ruined but, this is not very DRY I also left it in the model for normal user facing forms. I can't put the code in here but I've temporarily put in on dpaste [link]http://dpaste.com/2J94DW8. If anyone comes up with a DRYer method I'd love to hear about it. – chewinggumking May 19 '17 at 19:42

0 Answers0