I have a feedback form and it should be located on the main page along with other models. But alas, for some reason it refers to a non-existent template. And thus it is not shown on the site, although the model itself is present in the admin panel.
Please help me figure it out.
I was trying many ways to figure out it, but theres nothing
views.py
class MainDetail(CreateView):
success_url = reverse_lazy('success_page')
form_class = ContactForm
def get(self, request, **kwargs):
search_query = request.GET.get('search', )
model_2 = Jobs.objects.order_by()
form = ContactForm(request.POST)
portfolio = Portfolio.objects.prefetch_related('image')
ctx = {
'jobs':model_2,
'portfolio': portfolio
}
form = ContactForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'homepage.html', ctx)
def form_valid(self, form):
# Формируем сообщение для отправки
data = form.data
subject = f'Сообщение от {data["first_name"]} {data["last_name"]},Тема: ORDER {data["phone"]}'
email(subject, data['message'])
return super().form_valid(form)
model.py
class Contact(models.Model):
first_name = models.CharField ('Name', max_length=25)
last_name = models.CharField('Last Name', max_length=30)
phone = models.EmailField ('Phone', max_length=15)
message = models.TextField (max_length=400)
class Meta:
verbose_name= 'Feedback'
verbose_name_plural = 'Feedsbacks'
def __str__(self):
class Meta:
verbose_name= 'Feedback'
verbose_name_plural = 'Feedsbacks'
def __str__(self):
return self.first_name
forms.py
class ContactForm(ModelForm):
class Meta:
model = Contact
fields = ['first_name', 'last_name', 'phone', 'message']
widgets = {
'first_name': forms.TextInput (
attrs={'placeholder':'Name'}
),
'last_name': forms.TextInput(
attrs={'placeholder': 'Wash'}
),
'phone': forms.TextInput(
attrs={'placeholder': '+7 (123) 45-67-89'}
),
'message': Textarea(
attrs={
'placeholder': 'Message',
"rows":6,
"cols": 25
}
)
}
html
<aside class="postcard">
<form class="form" method="POST">
<p>Order</p>
{% csrf_token %}
{{ form.as_p }}
<div class="form-group">
<input type="submit" value="Send">
</div>
</form>
</aside>
Thanks for any help
Here it is the solution to all the troubles
class MainDetail(CreateView):
model = Jobs
model_2 = Portfolio
model_3 = Contact
template_name = 'homepage.html'
success_url = reverse_lazy('success_page')
form_class = ContactForm
def get_context_data(self, **kwargs):
context = super(MainDetail, self).get_context_data(**kwargs)
context['first_form'] = ContactForm (self.request.POST)
context['jobs'] = Jobs.objects.order_by()
context['portfolio'] = Portfolio.objects.prefetch_related('image')
return context
Related
I am trying to update multiple objects, however i am stumped on what i am doing wrong. I get queryset of objects i need to update, by filtering by schoolName(this is how my DB looks like), but I get "'ListSerializer' object is not iterable" when I include {% render_form serializer %} in my template.
I have uploaded my project to github
Relevant code:
models.py:
class School(models.Model):
schoolName = models.CharField(max_length=200, default='No Data')
className = models.CharField(max_length=200, default='No Data')
studentName = models.CharField(max_length=200, default='No Data')
studentGrade = models.IntegerField(null=True, blank=True)
professorName = models.CharField(max_length=200, default='No Data')
def __str__(self):
return self.schoolName
serializers.py:
class SchoolPartListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
# Maps for id->instance and id->data item.
school_mapping = {school.id: school for school in instance}
data_mapping= {schoolName['id']: schoolName for schoolName in validated_data}
# Perform creations and updates.
ret = []
for school_id, data in data_mapping.schoolName():
school = school_mapping.get(school_id, None)
if school is None:
ret.append(self.child.create(data))
else:
ret.append(self.child.update(school, data))
# Perform deletions.
for school_id, school in school_mapping.schoolName():
if school_id not in data_mapping:
school.delete()
return ret
class SchoolPartSerializer(serializers.Serializer):
id = serializers.IntegerField()
class Meta:
list_serializer_class = SchoolPartListSerializer
model = School
fields = ('id', 'url', 'schoolName')
extra_kwargs = {
'id':{
'read_only': False,
'allow_null': True,
},
'schoolName':{
'required': True,
}
}
views.py:
class SchoolDetail(APIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'tmp_school_detail.html'
def get(self, request, name, *args, **kwargs):
school = School.objects.filter(schoolName=name)
serializer_context = {'request': request, }
serializer = SchoolPartSerializer(instance=school, many=True, context=serializer_context)
return Response({'serializer': serializer, 'school': school})
def post(self, request, name):
school = School.objects.filter(schoolName=name)
#school = get_object_or_404(School.objects.only('id', 'schoolName'))
serializer_context = {'request': request,}
serializer = SchoolPartSerializer(instance=school, many=True, data=request.data, context=serializer_context)
if not serializer.is_valid():
return Response({'serializer': serializer, 'school': school})
serializer.save()
return redirect('tmp_school-list')
urls.py:
path(r'tmp_school_list/', views.SchoolList.as_view(), name='tmp_school-list'),
path(r'tmp_school_detail/<str:name>/', views.SchoolDetail.as_view(), name='tmp_school-detail'),
tmp_school_list.html:
{% load rest_framework %}
<html><body>
<h1>School - {{ school.schoolName }}</h1>
<form action="{% url 'tmp_school-detail' name=school.first.schoolName %}" method="POST">
{% csrf_token %}
{% render_form serializer %}
<input type="submit" value="Save">
</form>
Back
</body></html>
I have tried following documentation and have looked for other solutions(this one the best one i found), but nothing worked for me.
The goal is to update all data enteries that has a specificl schoolName.
When I query all the comments of the post, I want to return the user's username.
My two Models:
class Comment(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
post = models.ForeignKey(
Post, on_delete=models.CASCADE, null=False, blank=False)
title = models.TextField()
date = models.DateField(auto_now=True)
class User(AbstractUser):
objects = UserManager()
username = models.CharField(max_length=60, unique=True)
avi_pic = models.ImageField(
_('avi_pic'), upload_to=aviFile, null=True, blank=True)
My Comments Serializer:
class CommentSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField('get_username_from_user')
avi_pic = serializers.SerializerMethodField('get_avi_pic')
class Meta:
model = Comment
fields = '__all__'
def get_username_from_user(self, comment):
username = comment.user.username
return username
def get_avi_pic(self, comment):
request = self.context['request']
avi_pic = comment.user.avi_pic.url
return request.build_absolute_uri(avi_pic)
My Comments View:
class CommentView(APIView):
authentication_class = [authentication.TokenAuthentication]
permission_class = [permissions.IsAuthenticated]
serializer_class = CommentSerializer
# Get all comments from current post
def get(self, request):
post_id = request.data.get('id')
post = Post.objects.get(id=post_id)
comment = Comment.objects.filter(post=post).values()
serializer = CommentSerializer(comment)
return Response(serializer.data, status=status.HTTP_200_OK)
In my console I get: 'QuerySet' object has no attribute 'user'
Appreciate any help!!
In views.py:
comment = Comment.objects.filter(post=post)
In serializer.py:
def get_username_from_user(self, comment):
username = comment.user.username
return username
In views.py:
def get(self, request):
...
serializer = CommentSerializer(comment, many=True)
...
In my humble opinion, your problem is not having a ForeignKey for the "User" model, meaning whatever model you are trying to render doesn't have a column named 'user'. I'd do something like this:
models.py
class User(AbstractUser):
pass
def __str__(self):
return f"{self.username}"
class Comment(models.Model):
comment = models.TextField(max_length=300, null=True)
creation_date = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(User, on_delete=models.CASCADE)
whatever_name = models.ForeignKey(whatever_model_to_relate, on_delete=models.CASCADE, related_name="comments")
forms.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ['comment']
widgets = {
'comment': forms.Textarea(attrs={'rows':4, 'cols':100}),
}
views.py
#login_required
def whatever_function(request, id):
whatever_name = whatever_related_model.objects.get(id=id)
return render(request, "template.html", {
"whatever_name_for_template": whatever_name,
"commentform": CommentForm()
})
template.html
{% for comment in whatever_related_model.comments.all %}
<div class="card p-1 m-2 col-lg-12 col-sm-12">
<div class="card-body">
<h5 class="card-title">{{ comment.user }}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{ comment.creation_date }}</h6>
{{ comment.comment }}
</div>
</div>
{% endfor %}
Hopefully I didn't get sidetracked from your question.
I am having a problem with getting some additional fields to show up on the website. I want to have the viewer be able to add their phone_number and their birth_date but the form that I created is not showing up. If anyone could give me some direction, been trying this for 3 days.
Code
.view.py
def Profile(request):
args = {'user': request.user}
return render(request, 'index/profile.html', {})
def update_profile(request, user_id):
user = User.objects.get(pk=user_id)
user.save()
class ProfileUpdateView(LoginRequiredMixin, TemplateView):
user_form = UserForm
profile_form = ProfileForm
template_name = 'profile.html'
def post(self, request):
post_data = request.POST or None
user_form = UserForm(post_data, instance=request.user)
profile_form = ProfileForm(post_data, instance=request.user.profile)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Your profile was successfully updated!')
return HttpResponseRedirect(reverse_lazy('profile'))
context = self.get_context_data(
user_form=user_form,
profile_form=profile_form
)
return self.render_to_response(context)
def get(self, request, *args, **kwargs):
return self.post(request, *args, **kwargs)
.model.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone_number = models.IntegerField(default="", editable=True)
birth_date = models.DateTimeField(null=True, blank=True)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
.form.py
from django import forms
from django.contrib.auth.models import User
from .models import Profile
from django.contrib.auth.forms import UserChangeForm
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
widgets = {
'first_name': forms.TextInput(attrs={'class': 'form-control'}),
'last_name': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.TextInput(attrs={'class': 'form-control'}),
}
class UserUpdateForm(UserForm, UserChangeForm):
first_name = forms.CharField(
required=True, widget=forms.TextInput(attrs={'class': 'form-control'})
)
last_name = forms.CharField(
required=True, widget=forms.TextInput(attrs={'class': 'form-control'})
)
email = forms.EmailField(
required=True, widget=forms.TextInput(attrs={'class': 'form-control'})
)
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('phone_number', 'birth_date')
widgets = {
'phone_number': forms.TextInput(attrs={'class': 'form-control'}),
'birth_date': forms.TextInput(attrs={'class': 'form-control'}),
}
class ProfileUpdateForm(ProfileForm, UserChangeForm):
phone_number = forms.IntegerField(
required=True, widget=forms.TextInput(attrs={'class': 'form-control'})
)
birth_date = forms.CharField(
required=True, widget=forms.TextInput(attrs={'class': 'form-control'})
.profile.html
{% block body %}
<h2>{{ user.get_full_name }}</h2>
<p>Username: {{ user.username }}</p>
<p>Phone Number: {{ user.profile.phone_number }}</p>
<p>Birth Date: {{ user.profile.birth_date }}</p>
<div class="container">
<form method="post">
{{user_form.as_p}}
{{profile_form.as_p}}
<button type="submit">Submit</button>
</form>
<br>
</div>
OR,
<form method="post">
{{ user_form.as_p }}
{{ profile_form.as_p }}
<button type="submit">Save changes</button>
</form>
{% endblock %}
There is no place to enter the phone_number and birth_date
Took a 2 day break and came back to this issue.
The main issue was that I was trying to do too much and made it overly complex. Easy is the answer.
I am new to Django and need a help.
I want to allow users to update their account data using form, but struggle with associating Django User model with my UserProfile model, which extends default model with some additional fields.
I found, that solution is to create my own model form, but unfortunately I'm not exactly sure how to implement it.
models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User)
description = models.CharField(max_length=100, default='')
city = models.CharField(max_length=100, default='')
website = models.URLField(default='')
phone = models.IntegerField(default=0)
image = models.ImageField(upload_to='profile_image', blank=True)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
forms.py:
class EditProfileForm(UserChangeForm):
image = forms.ImageField(required=False)
city = forms.CharField(required=False)
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name',
'password',
'image',
'city'
)
views.py:
def edit_profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect(reverse('accounts:view_profile'))
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/edit_profile.html', args)
edit_profile.html:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
You are looking for Inline formsets. Just read the docs, it's pretty simple.
model.py
class FormData(models.Model):
email = models.EmailField()
full_name = models.CharField(max_length=120)
text_area = models.CharField(max_length=250)
radio_buttons = models.CharField(max_length=25)
check_boxes = models.CharField(max_length=10)
def __unicode__(self):
return self.email
forms.py
class MyModelForm(forms.ModelForm):
class Meta:
model = FormData
fields = ['text_area','email','full_name']
widgets = {
'text_area': Textarea(attrs={'cols': 50, 'rows': 10}),
}
TYPE_CHOICES = [('s', 'small'),('m', 'medium'),('b', 'big')]
check_boxes = forms.MultipleChoiceField(choices=TYPE_CHOICES, widget=forms.CheckboxSelectMultiple())
CHOICES = [(1, 'One'),(2, 'Two'),(3, 'Three'),(4, 'Four')]
radio_buttons = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect())
views.py
def home(request):
title = 'Welcome'
form = MyModelForm(request.POST)
context = {"title":title,"form":form}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {"title":"Thank You!"}
return render(request,"home.html",context)
home.html
<h1>{{title}}</h1>
<form method='POST' action=''>{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
The problem is that I can't seem to understand how to save the data from the checkboxes and the radiobuttons. The form gets submitted successfully but when I look in the database the field of check_boxes is empty and the radio_buttons field shows a value "False" while I need my manual values as defined in the CHOICES list.
You have added two extra fields in your form which you have not mentioned in fields. Change your form like this.
class MyModelForm(forms.ModelForm):
class Meta:
model = FormData
fields = ['text_area','email','full_name', 'check_boxes', 'radio_buttons']
widgets = {
'text_area': Textarea(attrs={'cols': 50, 'rows': 10}),
}
TYPE_CHOICES = [('s', 'small'),('m', 'medium'),('b', 'big')]
check_boxes = forms.MultipleChoiceField(choices=TYPE_CHOICES, widget=forms.CheckboxSelectMultiple())
CHOICES = [(1, 'One'),(2, 'Two'),(3, 'Three'),(4, 'Four')]
radio_buttons = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect())