im getting this error "NOT NULL constraint failed: myfiles_document.user_id"
what im trying to do is attach files to user ForeignKey so user can only see what they upload im using this app django-file-form here the code for the project
model.py
class Example2(models.Model):
title = models.CharField(max_length=255)
class ExampleFile(models.Model):
fs = FileSystemStorage(location=settings.MEDIA_ROOT)
input_file = models.FileField(max_length=255, upload_to='uploads/%Y.%m.%d' , storage=fs)
user = models.ForeignKey('auth.User')
def get_upload_path(self,filename):
return "static/uploads/"+str(self.user.id)+"/"+filename
forms.py
class BaseForm(FileFormMixin, django_bootstrap3_form.BootstrapForm):
title = django_bootstrap3_form.CharField()
class MultipleFileExampleForm(BaseForm):
input_file = MultipleUploadedFileField()
def save(self):
example = Example2.objects.create(
title=self.cleaned_data['title']
)
for f in self.cleaned_data['input_file']:
ExampleFile.objects.create(
input_file=f
)
self.delete_temporary_files()
views.py
class BaseFormView(generic.FormView):
template_name = 'example_form.html'
def get_success_url(self):
return reverse('example_success')
def form_valid(self, form):
form.save()
return super(BaseFormView, self).form_valid(form)
class ExampleSuccessView(generic.TemplateView):
template_name = 'success.html'
class MultipleExampleView(LoginRequiredMixin, BaseFormView):
form_class = forms.MultipleFileExampleForm
Your foreign key will not be automatically set to the current user unless you do it manually. That's why you are getting the not-null constraint error. Try modifying your form_valid method like this:
def form_valid(self, form):
form.instance.user = self.request.user
...
Read Django's documentation on models and request.user for details.
Related
hey I'm trying to make a question and answer project for django, how do I get the pk of the question that I am viewing right now to send an answer? I already set it up so that the url of the answer has /answer/pk of the question but I dont know how to get that info so the code knows where to post the model, how do I do that? also here is my code, thanks!
views.py
class AnswerForm(SuccessMessageMixin, CreateView):
template_name = 'forum/answer-question.html'
model = Answer
form_class = AnswerForm
success_message = 'Success!'
def form_valid(self, form, pk=None):
form.instance.question_id = Question.objects.only('id')
form.instance.user = self.request.user
form.save()
return super().form_valid(form)
forms.py
class AnswerForm(ModelForm):
class Meta:
model = Answer
fields = ['detail']
exclude = ('user', 'add_time')
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('questions/', views.QuestionsView.as_view(), name='questions'),
path('ask/', views.AskForm.as_view(), name='ask'),
path('answer/', views.AnswerForm.as_view(), name='answer'),
path('answer/<pk>', views.AnswerForm.as_view(), name='answer_with_pk'),
path('question/<pk>', views.QuestionDetailView.as_view(), name='detail'),
path('save-text', views.WriteCommentAnswerView.as_view(), name='save-text'),
path('save-vote', views.SaveVoteView.as_view(), name='save-vote'),
]
models.py
class Answer(VoteModel, models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
detail = models.TextField()
add_time = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return f"/questions/"
def __str__(self):
return self.detail
In AnswerForm you get all url parameters added to self because of base class DetailedView. In your case "self.pk". You can then add anything to the context for the html rendering by implementing get_context_data:
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in the publisher
context['question_pk'] = self.pk
return context
See https://docs.djangoproject.com/en/4.0/topics/class-based-views/generic-display/
I want to create article form in Django. The code below getting Error FileModel.post" must be a "Article" instance. because i want to create multiple file related article instances which is coming from forgnekey. i need to pass example post=form.instances when i submit form data but i don't understand how can i pass FileModel.objects.create(post=self.form_class, file=f)? I would be grateful for any help.
views.py
class CreateView(CreateView):
form_class = FileForm
template_name = 'create.html'
success_url = '/'
success_message = "New story has been created successfully"
def form_valid(self, form):
form.instance.author = self.request.user
for f in self.request.FILES.getlist('file'):
FileModel.objects.create(post=self.form_class, file=f) # Error is here!
return super().form_valid(form)
You need to pass the instance created by the form, rather than just the form class. For example:
FileModel.objects.create(post=form.instance, file=f)
Update: As the Article hasn't been saved yet, when you try to attach it to the FileModel object, it won't let you.
Try something like this:
def form_valid(self, form):
post = form.save(commit=False)
post.author = self.request.user
post.save()
for f in self.request.FILES.getlist('file'):
FileModel.objects.create(post=post, file=f)
return redirect('/')
I am working on a car rental website for uber drivers in django, from the detailView I need drivers to be able to choose the duration of their rental, and other information will be auto filled to the form from my views.py, i was able to get the driver through request.user, i also need the PK of the car to be rented. searching through here i’ve tried various suggestions by people here, but i keep getting one error after another…
using
self.kwargs['pk'] results in ValueError at /car/offer/4/ Cannot assign "4": "CarRent.car" must be a "Car" instance.
then i tried using
form.car = Car.objects.get(pk= self.kwargs.get('pk')) which results in a AttributeError at /car/offer/4/ 'CarRent' object has no attribute 'is_valid'
can someone please tell me how to get the car instance saved in the CarRent model? any help will be greatly appreciated. Thanks
below is my code (reduced to the relevant bit)
models.py
class Car(models.Model):
car_owner = models.ForeignKey(User, related_name='car_owner', on_delete=models.CASCADE)
class CarRent(models.Model):
car = models.ForeignKey(Car, related_name='rented_car', on_delete=models.CASCADE)
driver = models.ForeignKey(User, related_name='driver_renting', on_delete=models.CASCADE)
rented_weeks = models.BigIntegerField(default=1, choices=WEEK_CHOICES)
forms.py
class RentForm(forms.ModelForm):
class Meta:
model = CarRent
fields = ['rented_weeks']
i’m only displaying the rented weeks as that’s the only information i need from the user.
views.py
class CarView(FormMixin, DetailView):
model = Car
form_class = RentForm
def get_success_url(self):
return reverse('car-details', kwargs={'pk': self.object.pk})
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
form = form.save(commit=False)
form.car = self.kwargs['pk']
form.driver = request.user
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super().form_valid(form)
form.car expects a Car object, not a string with the primary key, but you can simply use:
from django.contrib.auth.mixins import LoginRequiredMixin
class CarView(LoginRequiredMixin, FormMixin, DetailView):
# …
def post(self, request, *args, **kwargs):
form = self.get_form()
self.object = self.get_object()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.instance.car_id = self.kwargs['pk']
form.instance.driver = self.request.user
form.save()
return super().form_valid(form)
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin mixin [Django-doc].
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Dear StackOverFlow community,
Basing on a built-in user User model I've created my own model class called "ModelOfParticularPerson". The structure of it looks like this:
class ModelOfParticularPerson(models.Model):
user = models.OneToOneField(User)
nickname = models.CharField(max_length=100, null=True, unique=False)
uploaded_at = models.DateTimeField(auto_now_add=True, null=True)
email_address = models.EmailField(max_length=200, blank=False, null=False, help_text='Required')
description = models.CharField(max_length=4000, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True, blank=True)
Unfortunately, after loggin in with the usage of particular account, whenever I am trying to reedit the profile, I do get following error:
"Model of particular person with this User already exists."
Any advice is priceless.
Thanks.
ps.
views.py:
[..]
#method_decorator(login_required, name='dispatch')
class ProfileUpdateView(LoginRequiredMixin, UpdateView):
model = ModelOfParticularPerson
form_class = ModelOfParticularPersonForm
success_url = "/accounts/profile/" # You should be using reverse here
def get_object(self):
# get_object_or_404
return ModelOfParticularPerson.objects.get(user=self.request.user)
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
def post(self, request):
form = ModelOfParticularPersonForm(self.request.POST, self.request.FILES)
if form.is_valid():
print("FORM NOT VALID!")
profile = form.save(commit=False)
profile.user = self.request.user
profile.save()
return JsonResponse(profile)
else:
return render_to_response('my_account.html', {'form': form})
urls.py:
urlpatterns = [
[..]
url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
url(r'^accounts/profile/$', ProfileUpdateView.as_view(template_name='my_account.html'), name='my_account'),
]
forms.py
class ModelOfParticularPersonForm(ModelForm):
class Meta:
model = ModelOfParticularPerson
fields = '__all__'
widgets = {
'user':forms.HiddenInput(),
'uploaded_at':forms.HiddenInput(),
'created':forms.HiddenInput(),
}
You need to pass the instance to the form, otherwise Django will try to create a new object when you save it.
def post(self, request):
form = ModelOfParticularPersonForm(instance=self.get_object(), self.request.POST, self.request.FILES)
...
You should try to avoid overriding get or post when you're using generic class based views. You can end up losing functionality or having to duplicate code. In this case, it looks like you can remove your post method. In the form_valid method you can return a JsonResponse. You shouldn't have to set form.instance.user if you are updating an existing object.
def form_valid(self, form):
profile = form.save()
return JsonResponse(profile)
Finally, you should leave fields like user and uploaded_at out of the model form instead of making them hidden fields.
You're creating new forum in your post method of view, but you're not passing existing model object to it. That leads to creation of new model, which fails, because object already exists.
Instead of overwritting post method, put saving of object inside is_valid method and use already provided form object (passed to you by method parameter).
I'm trying to create a view of type CreateView. This view will take the form_class = CourseForm that I created and excluded some fields in it. The instructor field is a foriegnKey and I don't want the user to be able to control it in the form. It's a field that depends on the signed in user.
# forms.py
class CourseForm(forms.ModelForm):
class Meta:
model = Course
exclude = ['instructor', 'members', 'slug']
# ...
my view is as follows. I thought that by including the instructor value in initial would pass the profile instance when I submit
# views.py
#method_decorator(login_required, name='dispatch')
class CourseCreateView(CreateView):
model = Course
template_name = 'course_form.html'
success_url = reverse_lazy('course-create-complete')
form_class = CourseForm
def get_initial(self):
initial = super(CourseCreateView, self).get_initial()
initial = initial.copy()
profile = get_object_or_404(Profile, user__username=self.request.user)
initial['instructor'] = profile
return initial
# models.py
class Course(models.Model):
instructor = models.ForeignKey(Profile, related_name="Instructor")
# ... other fields
but the probelm is that whenever I submit the form I get the following error:
NOT NULL constraint failed: myapp_course.instructor_id
If you want to set the initial value of instructor field, you shouldn't exclude it from the form. You could instead make the field hidden.
Or you could include that in the exclude list, but then you shouldn't override get_initial method, but do the assignment manually:
class CourseCreateView(CreateView):
def form_valid(self, form):
self.object = form.save(commit=False)
# create instructor based on self.request.user
self.object.instructor = instructor
self.object.save()
return HttpResponseRedirect(self.get_success_url())
Check django doc about what does save(commit=False) do.
Also check django doc about form_valid function and how forms are handled in class based views.