I have a certain model:
class Problem(models.Model):
title = models.CharField(max_length=80)
problem_text = models.TextField(max_length=5000)
pub_date = models.DateTimeField(default=timezone.now)
votes = models.IntegerField(default=0)
wiki_answer = models.TextField(max_length=5000, null=False, default='', blank=True)
topic = models.CharField(max_length=50, blank=False)
position = models.CharField(max_length=50, null=True, blank=False)
user = models.OneToOneField(User, null=True, blank=False, unique=False)
And after adding more than one post written by one user Django raises an error even though a user is not supposed to be unique. Here is the full stack trace:
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
64. return self.cursor.execute(sql, params)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/mysql/base.py" in execute
112. return self.cursor.execute(query, args)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
226. self.errorhandler(self, exc, value)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in defaulterrorhandler
36. raise errorvalue
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
217. res = self._query(query)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _query
378. rowcount = self._do_query(q)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _do_query
341. db.query(q)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in query
280. _mysql.connection.query(self, query)
The above exception ((1062, "Duplicate entry '1' for key 'interview_questions_problem_user_id_105dd8d0_uniq'")) was the direct cause of the following exception:
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
149. response = self.process_exception_by_middleware(e, request)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
147. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "/Users/artemdremov/Documents/python/interview_project/interview_questions/views.py" in post
55. post.save()
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in save
708. force_update=force_update, update_fields=update_fields)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in save_base
736. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in _save_table
820. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in _do_insert
859. using=using, raw=raw)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
122. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/query.py" in _insert
1039. return query.get_compiler(using=using).execute_sql(return_id)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
1060. cursor.execute(sql, params)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
79. return super(CursorDebugWrapper, self).execute(sql, params)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
64. return self.cursor.execute(sql, params)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/utils.py" in __exit__
95. six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/utils/six.py" in reraise
685. raise value.with_traceback(tb)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
64. return self.cursor.execute(sql, params)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/mysql/base.py" in execute
112. return self.cursor.execute(query, args)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
226. self.errorhandler(self, exc, value)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in defaulterrorhandler
36. raise errorvalue
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
217. res = self._query(query)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _query
378. rowcount = self._do_query(q)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _do_query
341. db.query(q)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in query
280. _mysql.connection.query(self, query)
Exception Type: IntegrityError at /p/add/
Exception Value: (1062, "Duplicate entry '1' for key 'interview_questions_problem_user_id_105dd8d0_uniq'")
Django version 1.9.5.
Here is the view for adding post form:
class AddView(View):
template_name = 'interview_questions/add.html'
form_class = ProblemForm
success_url = '/'
# display blank form
def get(self, request):
if request.user.is_authenticated():
form = self.form_class(None)
return render(request, self.template_name, {'form': form, 'user': request.user})
else:
return redirect('interview_questions:index')
# process data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid() and request.user.is_authenticated():
post = form.save(commit=False)
post.pub_date = timezone.now()
post.user = request.user
post.save()
return redirect('interview_questions:index')
return render(request, self.template_name, {'form': form, 'user': request.user})
The error happens here:
"/Users/artemdremov/Documents/python/interview_project/interview_questions/views.py" in post
55. post.save()
And that's because you have this in your model.
user = models.OneToOneField(User, null=True, blank=False, unique=False)
unique=False has no effect here because there can be exactly one entry here.
OneToOneField
A one-to-one relationship. Conceptually, this is similar to a
ForeignKey with unique=True, but the “reverse” side of the relation
will directly return a single object.
There are three solutions
Change your OneToOneField to a ForeignKey
In your form validation make sure that a record does not exist
When creating the form check if an entry already exists and then allo the user to edit it.
I am giving an answer just for better understanding of what causes this error. And why the reason is invisible.
Lets say we have an object, let me call it node
class Node(models.Model):
next_node = models.OneToOneField("Node", blank = True, null=True)
previous_node = models.OneToOneField("Node", blank = True, null=True)
name = models.CharField(max_length=50, default = "Nodes Name")
Then in the interactive console. You can access it in terminal (linux, sorry not sure how windows works anymore) by python(3) manage.py shell.
I have just done the test that replicates this integrity error.
>>>first_node = Node()
>>> first_node.save()
>>> second_node = Node()
>>> second_node.save()
>>> third_node = Node()
>>> third_node.save()
>>> fourth_node = Node()
>>> fourth_node.save()
>>> first_node.next_node = second_node
>>> second_node.previous_node= first_node
>>> first_node.save()
>>> second_node.save()
>>> second_node.next_node = third_node
>>> third_node.previous_node=second_node
>>> second_node.save()
>>> third_node.save()
>>> second_node.next_node= fourth_node
>>> fourth_node.previous_node=second_node
>>> second_node.save()
>>> fourth_node.save()
Traceback (most recent call last):
File
"/home/user/.local/lib/python3.5/sitepackages/django/db/
backends/utils.py", line 64, in execute
..........
..........
..........
_mysql.connection.query(self, query)
django.db.utils.IntegrityError:
(1062, "Duplicate entry '2' for key 'previous_node_id'")
The reason why this error is being produced is because,
We already assigned second node as a previous node of third node.
We are attempting to assign it as the previous_node of fourth node again.
This can be a problem if you only conscious of the forward relationship of second node i.e what second node is pointing to and you forget the reverse relationship.
I think the best solution to your answer given the nature of your model is to change the OneToOne relationship to ForeignKey (so that one user can write several problems).
If one user has to have one problem. Then everytime you save a problem as suggested in e4c5's 2nd solution, you have to ensure that no user is already owning the problem.
This can be particularly important when you have to resave or re-factor a model. For example in the case where you are saving an old problem with a new user/another user or a new user with an old problem. In the latter for example, it might not occur to you, that a certain user is already pointing to that problem and you will crush into an integrity error.
If want to handle Duplicate exception in Django read this
How to avoid Duplicate exception
We can also avoid from this kind of exception first check Profile exist or not then create Profile if not existed.
We can achieve this using get_or_create() method.
Many times we need to make unique fields or unique_together in Model to achieve some business logic.
Example
User and Profile (OneToOne relationship)
One Profile is created for per user.
Handle Duplicate entry exception in Django:
If user already created their profile again want to create then we can easily handle duplicate entry of profile like this.
from django.db import IntegrityError
try:
profile = Profile.objects.create(user=someuser,imageUrl= url )
except IntegrityError:
pass
#Handle your exception here
Related
I'm using a Django Model with some many-to-many fields. I'm also using a ModelForm to generate the associated form. It is my understanding that, provided nothing else is overridden, Django should be able to handle many-to-many fields being saved in the ModelForm?
For me, attempting to do this is causing this error:
Internal Server Error: /cameramodel/create/
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/mixins.py", line 52, in dispatch
return super().dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 141, in post
if form.is_valid():
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 185, in is_valid
return self.is_bound and not self.errors
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 180, in errors
self.full_clean()
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 383, in full_clean
self._post_clean()
File "/usr/local/lib/python3.8/site-packages/django/forms/models.py", line 403, in _post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File "/usr/local/lib/python3.8/site-packages/django/db/models/base.py", line 1188, in full_clean
self.clean()
File "./schema/models.py", line 1439, in clean
if self.metering_modes is True:
File "/usr/local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 527, in __get__
return self.related_manager_cls(instance)
File "/usr/local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 838, in __init__
raise ValueError('"%r" needs to have a value for field "%s" before '
ValueError: "<CameraModel: Canon Canonflex R2000>" needs to have a value for field "id" before this many-to-many relationship can be used.
So I checked out the docs and it seems like I need to override the save method in the ModelForm. So I did this:
class CameraModelForm(ModelForm):
class Meta:
model = CameraModel
fields = '__all__'
def save(self, commit=True):
form = super(CameraModelForm, self).save(commit=False)
if commit:
form.save(commit=False)
form.save_m2m()
return form
and instead I'm getting a different error:
TypeError at /cameramodel/create/
save() got an unexpected keyword argument 'commit'
Request Method: POST
Request URL: http://localhost:8000/cameramodel/create/
Django Version: 2.2.12
Exception Type: TypeError
Exception Value:
save() got an unexpected keyword argument 'commit'
Exception Location: /home/jonathan/git/camerahub/schema/models.py in save, line 1397
and models.py:1397 is actually an overridden Model save to add a slug field:
class CameraModel(models.Model):
# other stuff here
def save(self, *args, **kwargs):
if not self.slug:
custom_slugify_unique = UniqueSlugify(
unique_check=cameramodel_check, to_lower=True)
self.slug = custom_slugify_unique("{} {} {}".format(
self.manufacturer.name, self.model, str(self.disambiguation or '')))
super().save(*args, **kwargs)
For what it's worth, I am using many-to-many fields in some other models and I'm not seeing a problem with them. I'm a Python/Django beginner though and I'm pretty stuck on this one because simply following the advice on a million other posts like this one hasn't helped me. Grateful for any advice or code snippets anyone can offer.
If anyone needs more context, the whole project is open source and this branch is available here: https://github.com/djjudas21/camerahub/tree/278c_m2m_error
If you override, the save method, it means you want to make some checks/changes before saving your form. I would instead do:
def save(self):
form = super(CameraModelForm, self).save(commit=False)
if ...: # some condition on form values
form.save() # remove the commit here
form.save_m2m()
return form
I've made a django form in which I want to pass some context I need to display (mainly database entries in tags so the user can choose from them). I therefor made a get_context_data function where I add the context to the existing context like this:
def get_context_data(self, **kwargs):
context = super(UploadView, self).get_context_data(**kwargs)
context['categories'] = Category.objects.all()
context['form'] = VideoForm
return context
however, the form is not saving the information passed to the database. Why would that not work?
Here is part of my code!
forms.py:
class VideoForm(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label=None)
class Meta:
model = Video
fields = [
'title',
'description',
'description_short',
'category',
'time',
'thumbnail',
'type',
]
def clean_thumbnail(self):
picture = self.cleaned_data.get("thumbnail")
if not picture:
raise forms.ValidationError("No Image")
else:
w, h = get_image_dimensions(picture)
if w/h != (16/9):
raise forms.ValidationError("Image in wrong aspect ratio (should be 16:9)")
return picture
upload.html (it's pretty long so it's better to upload it to Pastebin)
views.py:
class UploadView(LoginRequiredMixin, CreateView):
form_class = VideoForm
template_name= 'upload.html'
def form_valid(self, form):
instance = form.save(commit=False)
instance.uploader=self.request.user
return super(UploadView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(UploadView, self).get_context_data(**kwargs)
context['categories'] = Category.objects.all()
context['form'] = VideoForm
return context
I'm using a custom form so I can set classes which I use for editing the CSS (instead of just using form.as_p and having a really ugly from there...)
EDIT:
After a bit more testing I found that if I put print(instance) inside the def form_valid(self, form): function it would not print out anything, suggesting the instance is empty. How can this be? Also, I tried removing: context['form'] = VideoForm and no errors show up but if I fill in the form correctly it still doesn't work!
EDIT 2:
I created a 'form_invalid' function like this:
def form_invalid(self, form):
print(form.instance)
return super(UploadView, self).form_invalid()
which causes:
TypeError: form_invalid() missing 1 required positional argument: 'form'
This had me thinking as I am not receiving any errors when I get redirected back to the form after submitting. Here is the form I wrote: https://pastebin.com/3H6VRZR1
Also I tried testing it with just form.as_p which causes the same problem
EDIT 3:
After testing some of the answers we found out that the form of the HTML page itself is probably the cause as the form arrived in form_invalid() completely empty. I decided that I would try to use form.as_p again see if it still caused the same issue as my custom form. Now I'm getting a new error:
null value in column "category_id" violates not-null constraint
DETAIL: Failing row contains (8, test new fom reg, test-new-fom-reg, null, test, test, 2018-01-10 13:44:58.81876+00, 2018-01-10 13:44:58.818789+00, 1, thumbnails/test-new-fom-reg.png, 2, 1, /home/trie/Desktop/django/vidmiotest/media/videos/test.mp4).
with:
USER
admin
GET
No GET data
POST
Variable Value
title 'test new fom reg'
category '8'
type '1'
time '1'
description 'test'
csrfmiddlewaretoken `BeizxWHU5KDbixit9vpxKoxEeBxgU9MNITaNlkM1qtI0Aq6kIThHrtjfUsQXjxON'
description_short 'test'
FILES
Variable Value
thumbnail <TemporaryUploadedFile: sixteentonineratio.png (image/jpeg)>
videoFile <TemporaryUploadedFile: test 3.mp4 (video/mp4)>
as the data the data send from the form which suggest (based on this) that category_id is not in my model for the form. which it is (the field is just called category), but why would it think it should be in there?
I just checked phppgadmin to see what the database looked like and there the field is called id_category while in my model it's called category, why?
EDIT 4: I never added the Traceback for the error above:
Internal Server Error: /upload/
Traceback (most recent call last):
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: null value in column "category_id" violates not-null constraint
DETAIL: Failing row contains (12, test, test, null, test, test, 2018-01-16 18:18:25.907513+00, 2018-01-16 18:18:25.907538+00, 6, thumbnails/test_d1MHjMX.png, 2, 1, /home/trie/Desktop/django/vidmiotest/media/videos/test.mp4).
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/contrib/auth/mixins.py", line 52, in dispatch
return super().dispatch(request, *args, **kwargs)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/views/generic/base.py", line 89, in dispatch
return handler(request, *args, **kwargs)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/views/generic/edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/home/trie/Desktop/django/vidmiotest/upload/views.py", line 21, in form_valid
instance.save()
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/base.py", line 729, in save
force_update=force_update, update_fields=update_fields)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/base.py", line 759, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/base.py", line 842, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/base.py", line 880, in _do_insert
using=using, raw=raw)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/query.py", line 1125, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1280, in execute_sql
cursor.execute(sql, params)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/trie/Desktop/django/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: null value in column "category_id" violates not-null constraint
DETAIL: Failing row contains (12, test, test, null, test, test, 2018-01-16 18:18:25.907513+00, 2018-01-16 18:18:25.907538+00, 6, thumbnails/test_d1MHjMX.png, 2, 1, /home/trie/Desktop/django/vidmiotest/media/videos/test.mp4).
The problem in the question is that super().form_valid() is called and overwriting the constructed form with context['form'] = VideoForm.
Let the framework setup the form when using CreateView.
The inherited CreateView provides the functionality to setup the form, save the form, set self.object on the view, and redirect to a success url.
I.e CreateView.form_valid provides:
self.object = form.save()
The solution is correct to set the uploader in UploadView, but calling the super.form_valid will try to save the form again.
As I understand the desired behaviour is:
set uploader
save the object
redirect to success url
in code:
instance = form.save(commit=False)
instance.uploader = self.request.user
instance.save()
return redirect(self.get_success_url()) # Skip the call to super
Also as pointed out in other answer, the context['form'] = VideoForm will overwrite the form setup by the CreateView.
I suggest to look how the execution flow works for the CreateView, it will setup the form for the template context both in GET and POST situation.
One other way to solve it is to allow the VideoForm to accept uploader in init:
class VideoForm(forms.ModelForm):
def __init__(self, uploader, *args, **kwargs):
self.uploader = uploader
super().__init__(*args, **kwargs)
def save(self, commit=True):
instance = super().save(commit=False)
instance.uploader = self.uploader
if commit:
instance.save()
return instance
and provide the uploader to the form
class UploadView(..., CreateView):
def get_form_kwargs(self):
kwargs= super().get_form_kwargs()
kwargs['uploader'] = self.request.user
return kwargs
Hope it helps.
Looking at EDIT 3:
The reason it's say 'category_id' is that foreign keys in a django model will automatically get suffixed with '_id' as column name in the database. Documentation.
The Video model is likely to have a foreign key to Category.
If you find id_category in database, you might have gone out of sync with your migrations/models? You should probably try clear the database and/or to re-run makemigrations/migrate
You certainly don't need that context['form'] = VideoForm line. Apart from anything else, it's overwriting the existing form so that your template will never see any errors.
I am using the django-multiupload app found at https://github.com/Chive/django-multiupload.
This appears to work well but I was using a modelform previously and replaced my prior form field with a widget with their default multipupload field.
This doesn't seem to have a formfield for modelforms. Would my form still function in the same way?
It seems that the form.save() function is not acting accordingly, I get this error:
Traceback: File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/agatorano/Code/metascape/metascape.org/source/uploads/views.py" in new_page
81. form.save(for_page=sess_) File "/Users/agatorano/Code/metascape/metascape.org/source/uploads/forms.py" in save
43. return super().save() File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/forms/models.py" in save
457. construct=False) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/forms/models.py" in save_instance
103. instance.save() File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/base.py" in save
590. force_update=force_update, update_fields=update_fields) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/base.py" in save_base
618. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/base.py" in _save_table
699. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/base.py" in _do_insert
732. using=using, raw=raw) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
92. return getattr(self.get_queryset(), name)(*args, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/query.py" in _insert
921. return query.get_compiler(using=using).execute_sql(return_id) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
919. for sql, params in self.as_sql(): File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in as_sql
877. for obj in self.query.objs File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in <listcomp>
877. for obj in self.query.objs File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in <listcomp>
875. for f in fields File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/fields/files.py" in pre_save
299. if file and not file._committed:
Exception Type: AttributeError at /list/new Exception Value: 'list' object has no attribute '_committed'
I know that this has to do with the fact multiple files are being saved in the form, but I don't know a solution.
my form:
from django import forms
from uploads.models import Document,Sess
from multiupload.fields import MultiFileField
from pandas_sql import *
class DocumentForm(forms.models.ModelForm):
#docfile = forms.FileField(widget=forms.FileInput(attrs={
# 'class':'filestyle','data-classButton':"btn btn-primary",
# 'data-input':"false",'data-classIcon':"icon-plus",
# 'data-buttonText':"Upload Data",}))
docfile = MultiFileField(min_num=1, max_num=3, max_file_size=1024*1024*5)
is_multiple = forms.BooleanField(label='Multi-Gene List',required=False,widget=forms.CheckboxInput())
class Meta:
model=Document
fields=('docfile','is_multiple',)
def clean_docfile(self):
docfile = self.cleaned_data.get('docfile',False)
name = docfile.name
extension = os.path.splitext(name)[1]
if extension != '.xls' and extension != '.xlsx':
raise forms.ValidationError("only excel files allowed ")
if docfile._size<int("27000"):
raise forms.ValidationError("File Not Large Enough For Upload")
return docfile
def save(self,for_page):
self.instance.sess = for_page
return super().save()
and here is my model:
from django.db import models
from django.core.urlresolvers import reverse
class Sess(models.Model):
def get_absolute_url(self):
return reverse('view_page',args=[self.id])
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
is_multiple = models.BooleanField(default=False)
sess = models.ForeignKey(Sess,default=None)
The commented part was my prior code. Do I need to revert my form file to a standard form file or does a modelform still work? Thank you
MultiFileField is for uploading more than one file at once and your model (which you didn't post) obviously has a single file field. There's a clear example of how to use MultiFileField with a model having a single file field in the doc
The problem it turns out was that the form.save() function couldn't handle creating multiple model objects with the multiple.
I had to manually create each model object for each file in the list of files.
So I think modelForms were not appropriate in this instance.
I'm running into a DB related problem in Django that I don't understand.
I define an MPTT model like so:
class Image(MPTTModel):
name = models.CharField(max_length=50)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
def rank(self): leaves = self.get_leafnodes() if leaves: rank = leaves[0].get_level() - self.get_level() else: rank = 0 return rank
mptt.register(Image, order_insertion_by=['name'])
Then in my views, I attempt a few statements with the model, and I get an OperationalError.
def index(request):
if request.method == 'POST':
image_string = request.POST.get('get_image')
index = image_string.find('(')
if index == -1:
parent = image_string
child = None
else:
parent = image_string[0:index]
child = image_string[index+1:len(image_string)-1]
try:
images = Image.objects.all()
image_names = [a.name for a in images]
except Image.DoesNotExist:
return render(request, 'images_app/index.html', {'images':[]})
else:
parent_model = Image(name=parent)
parent_model.save()
child_model = Image(name=child, parent=parent_model)
child_model.save()
return render(request, 'images_app/index.html', {'images':images})
I'm not sure if this is a problem with my view or the way I'm defining the model. According to my understanding, the 'try' expression should make it so that if the code doesn't evaluate, it will simply skip to the exception. Why doesn't this go straight to the exception?
Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\djangoprojects\images\images_app\views.py" in index
17. if images:
File "C:\Python27\lib\site-packages\django\db\models\query.py" in __nonzero__
100. self._fetch_all()
File "C:\Python27\lib\site-packages\django\db\models\query.py" in _fetch_all
854. self._result_cache = list(self.iterator())
File "C:\Python27\lib\site-packages\django\db\models\query.py" in iterator
220. for row in compiler.results_iter():
File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py" in results_iter
709. for rows in self.execute_sql(MULTI):
File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py" in execute_sql
782. cursor.execute(sql, params)
File "C:\Python27\lib\site-packages\django\db\backends\util.py" in execute
69. return super(CursorDebugWrapper, self).execute(sql, params)
File "C:\Python27\lib\site-packages\django\db\backends\util.py" in execute
53. return self.cursor.execute(sql, params)
File "C:\Python27\lib\site-packages\django\db\utils.py" in __exit__
99. six.reraise(dj_exc_type, dj_exc_value, traceback)
File "C:\Python27\lib\site-packages\django\db\backends\util.py" in execute
53. return self.cursor.execute(sql, params)
File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py" in execute
450. return Database.Cursor.execute(self, query, params)
Exception Type: OperationalError at /images/
Exception Value: no such table: images_app_image
By looking at the exception value (no such table: images_app_image), I would guess that the actual database table doesn't exist.
Check if the table exists in your database by using the ./manage dbshell command. You can list all tables in the database within the shell with the command .schema or use .schema images_app_image to only show the schema definition for the actual table.
If the table doesn't exist, create it with ./manage syncdb (or use the migrate command if you are using South).
Try python manage.py syncdb.
If you get
Unknown command: 'syncdb'
You can try
python manage.py migrate --run-syncdb
I am trying to extend the user model using AbstractUser component. But I haven't been successful on this. After reseraching lot I wrote my model Employee(Extended user model) but now I get the below error when I do syncdb.
If anyone can help me by suggesting or running my models.py that would be great. when I run syncdb it asks superuser creation after i give the credentials I get a below error.
Error : (Complete traceback is pasted after the models.py)
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: epi_employee.emp_id may not be NULL
My models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.conf import settings
# Create your models here.
class Employee(AbstractUser):
emp_id = models.IntegerField('Employee Id', max_length=5,unique=True)
dob = models.DateField('Date of Birth', null=True,blank=True)
def __unicode__(self):
return self.get_full_name
class Department(models.Model):
name = models.CharField('Department Name',max_length=30, unique=True,default=0)
def __unicode__(self):
return self.name
class Report(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
dept = models.ForeignKey(Department, verbose_name="Department")
report1 = models.ForeignKey(Employee,null=True,blank=True, verbose_name=u'Primary Supervisor',related_name='Primary')
report2 = models.ForeignKey(Employee,null=True,blank=True, verbose_name=u'Secondary Supervisor',related_name='Secondary')
def __unicode__(self):
return self.user
def upload_to(instance, filename):
return 'images/%s/%s' % (instance.user.username, filename)
class thumbnail((models.Model)):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
image = models.ImageField('Profile Pic',null=True, blank=True, upload_to=upload_to)
def __unicode__(self):
return self.user
class Passport(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
passport = models.CharField('Passport Number',max_length=15)
passportissue = models.CharField('Issuing City',max_length=15, default='Bangalore')
passportcountry = models.CharField('Issuing City',max_length=15, default='India')
passportstart = models.DateField('Valid From', null=True,blank=True)
passportend = models.DateField('Valid Till', null=True,blank=True)
def __unicode__(self):
return self.user
class CurrentAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
address = models.TextField('Current Address')
city = models.CharField('City', max_length=20, default = 'Bangalore')
state = models.CharField('State', max_length=20, default= 'Karnataka')
country = models.CharField('Country', max_length=20, default = 'India')
mobile1 = models.IntegerField('Mobile1',max_length=12)
mobile2 = models.IntegerField('Mobile2', null=True, blank=True, max_length=12)
landline = models.IntegerField('Land Line',null=True, blank=True, max_length=12)
email = models.EmailField('Personal Email Id', blank=True)
def __unicode__(self):
return self.user
COMPLETE TRACE BACK: Please find the complete error which I am getting. Let me know if more information required
(testenv1) F:\djangoenv\testenv1\employee>python manage.py syncdb
Creating tables ...
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table django_content_type
Creating table django_session
Creating table epi_employee_groups
Creating table epi_employee_user_permissions
Creating table epi_employee
Creating table epi_department
Creating table epi_report
Creating table epi_thumbnail
Creating table epi_passport
Creating table epi_currentaddress
You just installed Django's auth system, which means you don't have any superuse
rs defined.
Would you like to create one now? (yes/no): yes
Username: admin
Email address: admin#admin.com
Password:
Password (again):
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\__init__.
py", line 399, in execute_from_command_line
utility.execute()
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\__init__.
py", line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\base.py",
line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\base.py",
line 285, in execute
output = self.handle(*args, **options)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\base.py",
line 415, in handle
return self.handle_noargs(**options)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\commands\
syncdb.py", line 112, in handle_noargs
emit_post_sync_signal(created_models, verbosity, interactive, db)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\sql.py",
line 216, in emit_post_sync_signal
interactive=interactive, db=db)
File "F:\djangoenv\testenv1\lib\site-packages\django\dispatch\dispatcher.py",
line 185, in send
response = receiver(signal=self, sender=sender, **named)
File "F:\djangoenv\testenv1\lib\site-packages\django\contrib\auth\management\_
_init__.py", line 126, in create_superuser
call_command("createsuperuser", interactive=True, database=db)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\__init__.
py", line 159, in call_command
return klass.execute(*args, **defaults)
File "F:\djangoenv\testenv1\lib\site-packages\django\core\management\base.py",
line 285, in execute
output = self.handle(*args, **options)
File "F:\djangoenv\testenv1\lib\site-packages\django\contrib\auth\management\c
ommands\createsuperuser.py", line 141, in handle
self.UserModel._default_manager.db_manager(database).create_superuser(**user
_data)
File "F:\djangoenv\testenv1\lib\site-packages\django\contrib\auth\models.py",
line 195, in create_superuser
**extra_fields)
File "F:\djangoenv\testenv1\lib\site-packages\django\contrib\auth\models.py",
line 186, in _create_user
user.save(using=self._db)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\base.py", line
545, in save
force_update=force_update, update_fields=update_fields)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\base.py", line
573, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, upda
te_fields)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\base.py", line
654, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\base.py", line
687, in _do_insert
using=using, raw=raw)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\manager.py", li
ne 232, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\query.py", line
1511, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\models\sql\compiler.py
", line 898, in execute_sql
cursor.execute(sql, params)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\backends\util.py", lin
e 69, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\backends\util.py", lin
e 53, in execute
return self.cursor.execute(sql, params)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\utils.py", line 99, in
__exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\backends\util.py", lin
e 53, in execute
return self.cursor.execute(sql, params)
File "F:\djangoenv\testenv1\lib\site-packages\django\db\backends\sqlite3\base.
py", line 450, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: epi_employee.emp_id may not be NULL
You defined emp_id as unique but not nullable, you can add null=True to the model,but seems to be that you wanna use emp_id as a primari_key, so to ensure that the field can not be null and must be unique you maybe wanna use a models.AutoField:
emp_id = models.AutoField(primary_key=True)
this guarantee that the field is unique an can not be null.
Now, for the max_length property and the model's name (Employee) I think that emp_id will be a number that the company gives you, for example my id in the company where I work is 0001544, so to avoid that problem you can create a custom manager:
from django.contrib.auth.models import BaseUserManager
class EmployeManager(BaseUserManager):
def create_user(self, username, email,emp_id, password=None):
if not username:
raise ValueError('Employers must have an username.')
if not email:
raise ValueError('Employers must have an email address.')
if not emp_id:
raise ValueError('Employers must have an employer id')
user = self.model(username=username, email=self.normalize_email(email), emp_id=emp_id)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, emp_id, password):
user = self.create_user(username, email, emp_id, password)
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
and then in the models file add this:
from myapp.managers import EmployeManager
and into your Employers Model ass this
objects = EmployeManager()
then you run python manage.py syncdb
hope this helps you, any doubt, tell me.
You defined emp_id unique but not nullable.
So when you created the superuser, django raises that emp_id can't be null.
If you want it as primary key remove that field.
If you want define it later put in emp_id field null=True
Anyway you can read here https://docs.djangoproject.com/en/dev/topics/db/models/#automatic-primary-key-fields
P.s. I see another error:
self.get_full_name()
But this is the super behaviour so you could delete it at all.