'BlogUpdateView' object has no attribute 'date' - django-views

So i tried Function based views, but still keep getting the same error, anyone that wants to try the error can do so on http://159.65.157.112/
Create an ID, put up a post and go to update
Model
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date = models.DateTimeField(default=datetime.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog-detail', kwargs={'id': self.id})
View
class BlogUpdateView(UpdateView):
template_name = "post_update.html"
form_class = BlogForm
def get_object(self):
id_ = self.kwargs.get("id")
return get_object_or_404(Post, id=id_)
def form_valid(self, form):
return super().form_valid(form)
form
class BlogForm(ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs=
{'class' : 'form-control', 'placeholder' : 'Enter title'}
))
content = forms.CharField(widget=forms.TextInput(attrs=
{'class' : 'form-control', 'placeholder' : 'Enter content here'}
))
class Meta:
model = Post
fields = ['title', 'content']

Anyone looking for the fix in this one, i got it working by replacing
def get_object(self):
**id_ = self.kwargs.get("id")**
return get_object_or_404(Post, id=id_)
id to pk

Related

django restframework object-level-validation

These are my models : Test, Skillarea, question
MODELS.PY :
class Test(BaseModel):
types = models.ManyToManyField(
TestType,
related_name='tests',
)
title = models.CharField(max_length=255)
summary = models.TextField()
def __str__(self):
return self.title
class SkillArea(BaseModel):
title = models.CharField(max_length=255)
test = models.ForeignKey('Test', on_delete=models.PROTECT, related_name='skill_areas')
questions = models.ManyToManyField(
'assessment.Question',
related_name='skill_areas',
)
def __str__(self):
return self.title
class Question(BaseModel):
question_text = models.TextField()
def get_absolute_url(self):
self.get_type_display()
def __str__(self):
return truncatewords(self.question_text, 7)
class TestType(BaseModel):
title = models.CharField(max_length=255)
def __str__(self):
return self.title
I want to have an updateserializer for updating, but the field "type" in the Test model, only can be updated if there is no question in Skillarea model which related to Test model( has the same id as updating test, in its test field)
I wrote these serializer and view but it doesnt know data['id'] which i used in validator and sends KeyError: 'id'
serializer.py :
class TestUpdateAPIViewSerializer(serializers.ModelSerializer):
def validate(self, data):
questions = SkillArea.objects.filter(test=data['id'], questions__isnull=False)
if questions.exists():
raise serializers.ValidationError("You may not edit type")
return data
class Meta:
model = Test
fields = (
'id',
'types',
'title',
'summary',
)
Views.py :
class TestUpdateAPIView(APIView):
def patch(self, request, pk):
test = Test.active_objects.get(pk=pk)
serializer = TestUpdateAPIViewSerializer(instance=test, partial=True, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
I think you can get the id from instance attribute.
class TestUpdateAPIViewSerializer(serializers.ModelSerializer):
def validate(self, data):
questions = SkillArea.objects.filter(test=self.instance.id, questions__isnull=False)
...

Trying to add slug to end of get_absolute_url function in models (Django)

I have a function in my Post model, a get_absolute_url which is a reverse for 'post-detail', it has kwargs for primary key , how do i add another for slug; which is in my Profile model.
At the moment I'm getting error :
NoReverseMatch at /post/26/tested123/update/
Reverse for 'post-detail' with keyword arguments '{'pk': 26}' not found. 1 pattern(s) tried: ['post/(?P[0-9]+)/(?P[-a-zA-Z0-9_]+)/$']
This error occurs when I click the update button on my update post page
feed model
feed/models.py
class Post(models.Model):
description = models.TextField(max_length=255)
pic = models.ImageField(upload_to='path/to/img', blank=True)
date_posted = models.DateTimeField(default=timezone.now)
user_name = models.ForeignKey(User, on_delete=models.CASCADE)
tags = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.description
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
profile model
users/models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.png', upload_to='profile_pics')
slug = AutoSlugField(populate_from='user')
bio = models.CharField(max_length=255, blank=True)
friends = models.ManyToManyField('Profile', blank=True)
def __str__(self):
return str(self.user.username)
def get_absolute_url(self):
return "/users/{}".format(self.slug)
views.py
#login_required
def post_detail(request, pk, slug):
post = get_object_or_404(Post, pk=pk)
user = request.user
is_liked = Like.objects.filter(user=user, post=post)
if request.method == 'POST':
form = NewCommentForm(request.POST)
if form.is_valid():
data = form.save(commit=False)
data.post = post
data.username = user
data.save()
return redirect('post-detail', pk=pk, slug=slug)
else:
form = NewCommentForm()
return render(request, 'feed/post_detail.html', {'post':post, 'is_liked':is_liked, 'form':form})
views.py
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['description', 'pic', 'tags']
template_name = 'feed/create_post.html'
def form_valid(self, form):
form.instance.user_name = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.user_name:
return True
return False
Your get_absolute_url in Post doesn't have slug in kwargs or I'm missing something? 'slug': self.user_name.profile.slug

Django: When form is submitted, auto-fill a field

I'm looking to auto-fill a field when I submit a form so it is identical to another field.
I have a createView with a modelForm. The idea is the user writes his/hers name, which then when submitted fills out the display_name field as well. I know it's weird "why have two of the same", but it has a purpose.
Here's my code - I'm guessing I need to create a context that gets the display_name and sets it to be equal to the name?
views.py
class CreateIdentity(CreateView):
template_name = 'admin/CreateIdentity.html'
model = Identity
form_class = CreateIdentityForm
queryset = Identity.objects.all()
def get_context_data(self, **kwargs):
context = super(CreateIdentity, self).get_context_data(**kwargs)
context["user_id"] = User.objects.get(username=self.request.user)
return context
def form_valid(self, form):
form.instance.user_id = self.request.user
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("view_identity_created_with_slug", kwargs={'slug': self.object.slug})
models.py
class Identity(models.Model):
name = models.CharField(max_length=200, null=False)
display_name = models.CharField(max_length=200)
slug = models.SlugField(max_length=100)
user_id = models.ForeignKey(User, db_column="username", on_delete=models.CASCADE, null=False)
forms.py
class CreateIdentityForm(forms.ModelForm):
name = forms.CharField(required=True, widget=forms.TextInput(attrs={
'spellcheck': "false",
"class": "identity_name_input",
'placeholder': "Write your identity"}),
)
class Meta:
model = Identity
fields = ["name"]
def __str__(self):
return self.name
In the .form_valid(…) [Django-doc], you can specify the display_name based on the cleaned data of the form:
class CreateIdentity(CreateView):
template_name = 'admin/CreateIdentity.html'
model = Identity
form_class = CreateIdentityForm
queryset = Identity.objects.all()
def get_context_data(self, **kwargs):
context = super(CreateIdentity, self).get_context_data(**kwargs)
context["user_id"] = User.objects.get(username=self.request.user)
return context
def form_valid(self, form):
form.instance.user_id = self.request.user
form.instance.display_name = form.cleaned_data['name']
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("view_identity_created_with_slug", kwargs={'slug': self.object.slug})

AttributeError 'NarrateUpdate' object has no attribute 'object'

I got an attribute error on my NarrateUpdate view. I want to edit/update a user submission from a form
Here's my views.py:
class NarrateUpdate(SuccessMessageMixin, UpdateView):
model = Narrate
fields = ['title', 'body']
template_name = 'narrate_update_form.html'
success_url = reverse_lazy('narrate-status')
success_message = "Narration successfully updated"
def get(self, request, *args, **kwargs):
footer = FooterLinks.objects.all()
context = self.get_context_data(**kwargs)
context['footer'] = footer
return self.render_to_response(context)
The urls.py
path('narration/<int:pk>/update/', NarrateUpdate.as_view(), name='edit-narration'),
And here's the models.py:
class Narrate(models.Model):
STATUS = (
('F', 'FOR REVIEW'),
('P', 'PASSED'),
)
title = models.CharField(max_length=255)
body = models.CharField(max_length=10000)
status = models.CharField(
max_length=25, choices=STATUS, default='for_review', blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return "/narration/%i/" % self.title
class Meta:
verbose_name = "narration"
verbose_name_plural = "narrations"
What can I do to make this work?
Why are you overriding the get method? If you want to add footer better to do it in get_context_data() method:
class NarrateUpdate(SuccessMessageMixin, UpdateView):
model = Narrate
fields = ['title', 'body']
template_name = 'narrate_update_form.html'
success_url = reverse_lazy('narrate-status')
success_message = "Narration successfully updated"
def get_context_data(self, **kwargs):
context = super(NarrateUpdate, self).get_context_data(**kwargs)
context['footer'] = FooterLinks.objects.all()
return context

How to specify a list of values ​in a form in which CheckboxSelectMultiple is used?

I have a problem with the form in django. It uses the CheckboxSelectMultiple widget, but I need to set a list of possible choices only for posts created by the currently logged in user.
Any idea?
form:
class CycleForm(BSModalForm):
class Meta:
model = Cycle
fields = ['title', 'description', 'posts']
widgets = {
'posts': forms.CheckboxSelectMultiple(),
}
models
class Cycle(models.Model):
title = models.CharField(max_length=200, unique=True)
description = models.TextField(max_length=500, default="Brak opisu")
date_created = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
posts = models.ManyToManyField(Post)
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=50, unique=True)
content = MDTextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
numbers_of_entries = models.IntegerField(default=0)
views
class CycleCreateView(BSModalCreateView, LoginRequiredMixin):
template_name = 'blog/cycle_form.html'
form_class = CycleForm
def form_valid(self, form, **kwargs):
form.instance.author = self.request.user
return super().form_valid(form)
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
class CycleUpdateView(BSModalUpdateView):
model = Cycle
template_name = 'blog/cycle_update.html'
form_class = CycleForm
success_message = 'Success: Cycle was updated.'
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
We can slightly alter the CycleForm form and add a user parameter. If that parameter is set, we filter the queryset of the posts field by only using Posts
class CycleForm(BSModalForm):
def __init__(self, *args, user=None, **kwargs):
super().__init__(*args, **kwargs)
if user is not None:
self.fields['posts'].queryset = Post.objects.filter(author=user)
class Meta:
model = Cycle
fields = ['title', 'description', 'posts']
widgets = {
'posts': forms.CheckboxSelectMultiple(),
}
Now we only need to pass the user to the form, we can override the get_form_kwargs method [Django-doc]:
class CycleCreateView(LoginRequiredMixin, BSModalCreateView):
template_name = 'blog/cycle_form.html'
form_class = CycleForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update(user=self.request.user)
return kwargs
def form_valid(self, form, **kwargs):
form.instance.author = self.request.user
return super().form_valid(form)
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
You should do the same with the UpdateView. Note that your LoginRequiredMixin likely should be put first in the base classes.