Update only ForeignKey field in Django form - python

I try to update a ForeignKey field of a model in django form. I want a user not to write his name into a input field as an author of the article that he wrote but his idmust be saved in the field in Article model. In my html-form I display only a button with hidden input. But in my views.py I write that the form should take user.id and put it in the 'article_author' field.
Unfortunately, I've got no updates into table. What am I doing wrong?
my model:
class Article(models.Model):
article_pub_date = models.DateField(default=None,null=True,verbose_name="Дата публикации")
article_title = models.CharField(max_length=70, verbose_name="Заголовок", null=True)
article_text = models.TextField(verbose_name="Текст", null=True)
article_author = models.ForeignKey(User, verbose_name='Автор', blank=True, null=True)
my views.py
def article_detail(request, article_id):
user = request.user
article = get_object_or_404(Article, pk=article_id)
author_form = ArticleForm(request.POST or None, instance=article, initial={'article_author': user.id})
if author_form.is_valid():
author_form.save()
else:
return redirect('/')
my forms.py
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('article_author',)
widgets = {'article_author': forms.HiddenInput()}
and my template:
<form method="POST" action="">
{% csrf_token %}
{{ author_form.as_p }}
<input type="submit" value="BIND" class="btn">
</form>

Try one of the following:
if author_form.is_valid():
article = author_form.save(commit=False)
article.article_author = user
# article.article_author_id = user.id #w ill work as well
article.save()
else:
return redirect('/')
or in the form instantiation:
initial={'article_author_id': user.id}

Related

Validation always True (blank=False) for CharField but not with DateField

I have an inlineformset_factory containing a field. When this field is a CharField (blank=False) and I run is_valid() on the formset, True is always returned even though the CharField is left blank. When I replace the CharField with a DateField (default=timezone.now(), blank=False), is_valid() will return True only when the field is filled as expected. Why is the CharField always returning True when running is_valid() on the formset but the DateField does not? Note that I want the CharField to behave like the DateField.
Interestingly enough, the formset behaves as expected when both the CharField and DateField are present.
Code below is shown with title and date but I have tried with only title and only date as described above. Any help is appreciated. This is driving me up the wall!
models.py
class Author(models.Model):
author = models.CharField(max_length=128)
description = models.CharField(max_length=1000)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
date = models.DateField(default=timezone.now(), blank=False)
forms.py
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ('author', 'description')
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ('title', 'date')
BookFormSet = forms.inlineformset_factory(
Author,
Book,
form=BookForm,
fields=('title', 'date'),
extra=1,
can_delete=False,
can_order=False
)
views.py
class CreateAuthorView(CreateView):
template_name = "author_create.html"
model = Author
form_class = AuthorForm
def get_context_data(self, **kwargs):
context = super(CreateAuthorView, self).get_context_data(**kwargs)
if self.request.POST:
form = self.get_form(self.form_class)
context["book"] = BookFormSet(self.request.POST, instance=form.instance)
else:
context["book"] = BookFormSet()
return context
def form_valid(self, form):
context = self.get_context_data()
book = context["book"]
print(form.data.get("author"))
print("book.is_valid()", book.is_valid()) # ***This always prints True when only CharField is part of Book model***
return redirect(self.get_success_url())
def get_success_url(self):
return reverse("author_list")
author_create.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form }}
</div>
<div>
{{ book.management_form }}
{% for book_form in book %}
<div>
{{ book_form }}
</div>
{% endfor %}
</div>
<button type="submit">Submit Author</button>
</form>
When dealing with formsets, completely empty forms are not validated unless the minimum/maximum number is set in the formset definition itself.

When I submit this form, neither data is saved onto database nor giving any error in my django project

models.py
here is my model
class Load_post(models.Model):
user = models.ForeignKey(get_user_model(),on_delete=models.CASCADE)
pick_up_station = models.CharField(max_length=150)
destination_station = models.CharField(max_length=150)
sender_name = models.CharField(max_length=150)
phone_number = PhoneNumberField(null=False , blank=False , unique=True)
receiver_name = models.CharField(max_length=150)
sending_item = models.CharField(max_length=150)
weight = models.CharField(max_length=150)
metric_unit = models.CharField(max_length=30, default='SOME STRING')
quantity = models.PositiveIntegerField(default=1)
requested_shiiping_price = models.PositiveIntegerField()
pick_up_time = models.DateField()
drop_time = models.DateField()
paid_by = models.CharField(max_length=150)
created_at = models.DateTimeField(auto_now=True)
published_date = models.DateField(blank=True, null=True)
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
def publish(self):
self.published_date = timezone.now()
self.save()
def get_absolute_url(self):
return reverse('local')
class Meta:
ordering = ["-created_at"]
unique_together = ["sender_name", "receiver_name"]
please check the phone number
forms.py
this is form.py
class Loader_post_form(forms.ModelForm):
phone_number = PhoneNumberField()
metric_unit = forms.ChoiceField(choices=UNIT, required=True)
class Meta:
model = Load_post
fields = ("pick_up_station", "destination_station",
"sender_name", "phone_number", "receiver_name",
"sending_item","image_of_load","weight","metric_unit",
"quantity","requested_shiiping_price","pick_up_time",
"drop_time","paid_by")
views.py
This is my views.py
absolute URL used in models already
class Loader_post_view(CreateView, LoginRequiredMixin):
login_url = 'Driver/login/'
form_class = forms.Loader_post_form
model = Loader_Signup
template_name = "Driver/post.html"
def form_valid(self,form):
form.instance.user = self.request.user
form.save()
return super(Loader_post_view,self).form_valid(form)
post.html
this is html page (template)
{% extends "Driver/base.html" %}
{% block content %}
<h1>create a post</h1>
{% csrf_token %}
{{form}}
<button type="submit">submit</button>
{% endblock content %}
this is html code
how to add it to the database
and I cannot see any error in my forms
thank you
am working on driver and client-side project
From what I see you html template cannot submit the form because you ae missing the <form> tags - if you do not have them hidden in your base.html.
Your html template should be something like this:
{% extends "Driver/base.html" %}
{% block content %}
<h1>create a post</h1>
<form method="POST">
{% csrf_token %}
{{form}}
<button type="submit">submit</button>
</form>
{% endblock content %}
The {{ form }} renders the form with all the inputs but does not create the tags needed for html forms.
In addition there are some other errors in the code you posted.
In your view the model you defined is called Loader_Signup, however the model you posted is Load_post. Either you posted the wrong model or you declared the wrong model in your view.
In your form one field is called image_of_load, however, this field is not part of you model.
In your model you have got a field called phone_number, you are defining a field with the same name in your form. The field in your form has got no connection to your model so take it out.
Unfortunately you are not providing any details about your PhoneNumberField so this cannot be checked.

FOREIGN KEY constraint failed , django

I have to insert the post through a form but when i submit i got this error FOREIGN KEY constraint failed, the problem is with the author field
models.py
class Post(models.Model):
STATUS_CHOICES = (
('draft','Draft'),
('published','Published'),
)
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=120)
author = models.ForeignKey('auth.User',related_name='blog_posts',on_delete=models.CASCADE,blank=True, null=True)
body = RichTextField()
created = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft')
tag = models.OneToOneField(Tag,related_name="blog_tag",on_delete=models.CASCADE,default=0)
def __str__(self):
return self.title
views.py
def tagView(request,name):
tag = Tag.objects.get(name=name)
post_form = PostForm(request.POST or None)
if request.method == 'POST':
post_form = PostForm(request.POST)
if post_form.is_valid():
item = post_form.save(commit=False)
item.author = request.user
item.save()
return HttpResponseRedirect(request.path_info)
context = {
'post_form' : post_form,
'tag' : tag,
}
return render(request,'blog/tagPage.html',context)
forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title','body']
template
<form class="post-form" method="POST" enctype="multipart/form-data" action="">
{% csrf_token %}
{{ post_form }}
<input class="post-form-submit submit" type="submit" value="Save">
</form>
If the author field is the problem, be sure to import auth.User
My guess is that you are trying to add the post as anonymous but anonymous user is not null (id is though). Also don't use 'auth.User' and follow the instructions from the documentation.

Details for model and form model on detail page

I have problem with connect two models on one page, detail page (Django 1.11).
I have model Event - I want to display details for this model on detail page - this is working for me.
class Event(models.Model):
title = models.CharField(max_length=500)
date = models.DateField()
text = models.TextField()
image = FilerImageField(null=True, blank=True)
free_places = models.IntegerField()
class Meta:
ordering = ['-date']
def __str__(self):
return self.title
On another hand I have model Register
class Register(models.Model):
event = models.ManyToManyField(Event)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
company = models.CharField(max_length=30, blank=True)
street = models.CharField(max_length=50, blank=True)
post_code = models.CharField(max_length=30, blank=True)
city = models.CharField(max_length=30, blank=True)
email = models.EmailField()
phone_number = models.IntegerField(max_length=30)
def __str__(self):
return self.first_name
I want to signup user on event with folder on detail page, below details for events.
Here is my detail view, where I want to display details for event and take data from user to Register model:
class EventDetailView(DetailView, FormMixin):
model = models.Event
form_class = forms.RegisterForm
def get_success_url(self):
return reverse('events:list')
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
Template:
{% extends 'base.html' %}
{% block content %}
<ul>
<h1>Detail page:</h1>
<li>{{ object.title }}</li>
<li>{{ object.text }}</li>
<li>{{ object.date }}</li>
</ul>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
After push submit button I have no items in Register model.
The default definition of form_valid on FormMixin is simply to redirect to the success URL. That's because it doesn't know anything about models, so it is not expecting a .save() method on the form.
You should use ModelFormMixin instead.

Django: ModelForms: ImageField is always empty and rejected by ModelForm

I created a form based on several ModelForm elements. All fields work fine excluding the
ImageField. Due to the missing ImageField form.is_valid() always returns False - even though I pass request.FILES to form.
Why the form with the ImageField is always invalid / empty?
Forms
class UserProfileForm2(forms.ModelForm):
class Meta:
model = models.UserProfile
fields = ['description', 'picture']
class LocationForm(forms.ModelForm):
class Meta:
model = models.Location
fields = ['city', 'state', 'country']
class UserForm(forms.ModelForm):
class Meta:
model = registration_models.User
fields = ['first_name', 'last_name']
Models
class Location(models.Model):
city = models.CharField(max_length=100)
state = models.CharField(max_length=100)
country = models.CharField(max_length=100)
def __unicode__(self):
return ' - '.join([self.city, self.state, self.country])
class UserProfile(models.Model):
authenticationuser = fields.AutoOneToOneField(AuthUser)
description = models.TextField()
picture = models.ImageField(upload_to='uploaded_files/', null=True)
location = models.ForeignKey(Location, null=True)
appear_in_public_ranking = models.BooleanField(default=True)
def __unicode__(self):
return self.authenticationuser.username
View
#login_required
def changeprofile(request):
form = None
# user posted his new profile settings
if request.method == 'POST':
user_form = myforms.UserForm(request.POST)
user_profile_form = myforms.UserProfileForm2(request.POST, request.FILES)
location_form = myforms.LocationForm(request.POST)
forms_are_invalid = not (user_form.is_valid() and user_profile_form.is_valid() and not location_form.is_valid())
if forms_are_invalid:
forms = {'user_form':user_form,
'user_profile_form':user_profile_form,
'location_form':location_form}
return shortcuts.render(request, 'changeprofile.html', forms)
location_form.save()
user_form.save()
user_profile_form.save()
return HttpResponseRedirect('/profile')
else:
forms = {'user_form':user_form,
'user_profile_form':user_profile_form,
'location_form':location_form}
return shortcuts.render(request, 'changeprofile.html', forms)
Template
<form action="{% url 'changeprofile' %}" method="post">
{% csrf_token %}
{{ user_form }}
{{ location_form }}
{{ user_profile_form }}
<input type="submit" value="Submit" />
</form>
If your form contains file input then you must set enctype in your form as:
<form action="{% url 'changeprofile' %}" method="post" enctype="multipart/form-data">
Otherwise request.FILES will always be empty.

Categories