Django URLs not updating after slug change - python

I use Slugify. After making a change in slug for all objects in Entry, slug still shows as old slug. If I refresh obj page, I get a page not found, unless I click "back" and then reopen the obj page, and that is when the obj page will load and new slug will update.
Any idea how to fix this?
I tried an empty migration and applied obj.save() and obj.refresh_from_db() but no luck.
Below is my model, this is what generates my slug field:
(My change was removed self.4 and replaced with self.5)
class Entry(models.Model)
1 = ...
2 = ...
3 = ...
4 = ...
5 = ...
slug = models.SlugField(null=True, unique=True, max_length=300)
def save(self, *args, **kwargs):
self.slug = slugify(f"{self.1}-{self.2}-{self.3}-{self.5}")
return super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("page", kwargs={"slug": self.slug})
View:
def post_page(request, slug):
form = PostForm()
entry = Entry.objects.get(slug=slug)
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.cleaned_data['post']
post = form.save(commit=False)
post.entry = entry
post.save()
return redirect('post_page', slug=entry.slug)
else:
msg_error = 'Please correct errors and resubmit'
return render(request, 'post_page.html', {'entry': entry, 'form':form, 'msg_error':msg_error})
return render(request, 'post_page.html', {'entry': entry, 'form':form})
Url:
path('post-page/<slug>/', views.post_page, name='post_page'),

try
path('post-page/<slug:slugname>/', views.post_page, name='post_page'),
def post_page(request, slugname):
form = PostForm()
entry = get_object_or_404(Entry, slug=slugname)
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.cleaned_data['post']
post = form.save(commit=False)
post.entry = entry
post.save()
return redirect('post_page', slug=entry.slug)
else:
msg_error = 'Please correct errors and resubmit'
return render(request, 'post_page.html', {'entry': entry, 'form':form, 'msg_error':msg_error})
return render(request, 'post_page.html', {'entry': entry, 'form':form})

You need to change URL pattern like this
path('post-page/<slug:slug>/', views.post_page, name='post_page'),

Found a solution
In shell:
for obj in Entry.objects.all():
obj.save()

Related

Django - Unable to find object using pk (Matching query DoesNotExist)

Whenever I try to create a "Tour" for a "User" I get this error:
"DoesNotExist at /add-tour/FAjK5CryF8/ - User matching query does not exist."
Specifically the problems seems to come from this line of code:
user = User.objects.get(pk=pk)
models.py
class Tour(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
tour_date = models.DateField(default=date.today)
tour_fans = models.ForeignKey(FanAccount, on_delete=models.PROTECT)
def __str__(self):
return f"{self.user} del {self.tour_date}"
views.py
def tour_new(request, pk):
user = User.objects.get(pk=pk)
if request.method == "POST":
form = TourForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.tour_fans = request.user
form.instance.user = user
instance.save()
form.save()
return render(request, "tour.html", {"form": TourForm(), "success": True})
else:
form = TourForm()
return render(request, "tour.html", {"form": form})
For "User" I'm using a custom Primary Key (ShortUUID).
I'm new to Python and Django so it may be something easily solvable, but after hours of attempts I seem unable to solve it.
You need to make sure your user instance does exist, so you should instead of user = User.objects.get(pk=pk)call user = get_object_or_404(User, pk=pk), then you need to pass user as an instance:
if request.method == "POST":
form = TourForm(request.POST, instance=user)

How to remove "this field is not required" in django?

I found posts with similar problem, but the solutions dont seem to work with me. Or maybe I am missing something.
I created a form in Django, but as a default it seems that every mandatory fields have this "this field is required" text above.
Ideally, I would like to have this only when someone tries to submit a form and a field is missing.
form.py
class ElderFlowerChampFormAdmin(ModelForm):
fieldsets=[
("Look",{'fields':[
('look_colour','look_clarity','look_effervescence')]}),
}
widgets = {
'user': forms.Select(attrs={'class':'form-control','required':'True'}),
'look_colour':forms.Select(attrs={'class':'form-control','required':'True'}),
}
view.py
def elderflowerchamp(request, product_id):
global ChampageRating
product = Product.objects.get(pk=product_id)
url = request.META.get('HTTP_REFERER')
submitted = False
try:
if request.method == "POST":
reviews = ChampageRating.objects.get(pk=product_id)
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin(request.POST, instance=reviews)
if form.is_valid():
form.save()
return redirect('home')
else:
form = ElderFlowerChampForm(request.POST, instance=reviews)
if form.is_valid():
ChampageRating = form.save(commit=False)
ChampageRating.user = request.user
ChampageRating.save()
return redirect('home')
else:
#This part goes to the page, but doesnt submit
reviews = ChampageRating.objects.get(pk=product_id)
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin
else:
form = ElderFlowerChampForm
if 'submitted' in request.GET:
submitted = True
except:
reviews = None
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin(request.POST)
if form.is_valid():
data = ChampageRating()
data.rating = form.cleaned_data['rating']
data.look_colour = form.cleaned_data['look_colour']
data.ip = request.META.get('REMOTE_ADDR')
data.product_id = product_id
data.user_id = request.user.id
data.save()
messages.success(request, 'Thank you! Your review has been submitted.')
return redirect('home')
else:
form = ElderFlowerChampForm(request.POST)
if form.is_valid():
data = ChampageRating()
data.rating = form.cleaned_data['rating']
data.look_colour = form.cleaned_data['look_colour']
data.ip = request.META.get('REMOTE_ADDR')
data.product_id = product_id
data.user_id = request.user.id
data.save()
messages.success(request, 'Thank you! Your review has been submitted.')
return redirect('home')
return render(request,"main/ElderFlowerReview.html", {'form':form, 'submitted':submitted,'reviews':reviews, 'product':product})
models.py
LOOKCOLOUR=(
(1,'Straw'),
(2,'Yellow'),
(3,'Gold'),
(4,'Amber'),
)
class ChampageRating(models.Model):
user = models.ForeignKey(User,blank=True, on_delete=models.CASCADE)
product=models.ForeignKey(Product,related_name="champcomments", on_delete=models.CASCADE)
look_colour=models.IntegerField(choices=LOOKCOLOUR, default=0)
def __str__(self):
return '%s - %s - %s'%(self.user, self.product, self.date_added)
Any ideas
something wrong on case request.GET here:
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin
else:
form = ElderFlowerChampForm
You send the FormClass into the template context, and not the form instance.
Also see eror on the except case: If i have a GET, i should not render BoundedForm, here should be form.bounded = false (form is not bounded with any data). But you are always made the BoundedForm, with the request.POST data after error here:
reviews = ChampageRating.objects.get(pk=product_id)
My opinion is - you should try to read about Django-GCBV, it is better way to avoid complex errors, like in your question.
https://docs.djangoproject.com/en/4.0/topics/class-based-views/

Class view with post, get and data

I have practically finished the microblogging application and I want to change to class base views now. I read about generic views, but it looks like each of them has specific properties. In my index view I display two models and two forms, so I created IndexView (View) and put the get and post functions there and it works, but it doesn't look like there are any benefits of class views, so I'm probably doing something wrong. Currently, several views repeat a lot of code, and I thought that class views would solve this problem. I would like an example of how such a view should be written as class view with reusable get.
class IndexView(View):
def get(self, request, *args, **kwargs):
post_form = AddPostForm()
comment_form = AddCommentForm()
if request.user.is_authenticated:
logged_user = CustomUser.objects.get(id=request.user.id)
blocked_users = logged_user.blocked.all()
posts = Post.objects.exclude(author__in=blocked_users)
print(blocked_users)
posts = posts.order_by('-pub_date')
else:
posts = Post.objects.all()
posts = posts.order_by('-pub_date')
comments = Comment.objects.all()
comments = comments.order_by("-pub_date")
return render(request, 'mikroblog/index.html', {'posts': posts, 'comments': comments,
'post_form': post_form, 'comment_form': comment_form})
def post(self, request, *args, **kwargs):
if request.method == 'POST':
post_form = AddPostForm(request.POST)
comment_form = AddCommentForm(request.POST)
if post_form.is_valid():
new_post = post_form.save(commit=False)
new_post.author = request.user
new_post.tags = ''
content = ''
for word in new_post.content_post.split():
if '#' in word:
new_post.tags += f"{word} "
content += f"{word} "
else:
content += f"{word} "
new_post.content_post = content
new_post.save()
for word in content.split():
if '#' in word:
print(word)
user_to_notificate = CustomUser.objects.get(username=word[1:])
new_notification = TalkAbout()
new_notification.where = new_post
new_notification._from = new_post.author
new_notification.to = user_to_notificate
new_notification.sended = False
print(new_notification)
new_notification.save()
post_form = AddPostForm()
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.author = request.user
new_comment.save()
comment_form = AddCommentForm()
return HttpResponseRedirect(reverse('index'))
Use class-based views and override the 'post' and 'get' methods if you need to.
Follow this link:
Django CBVs documentation

Django model form, adding a user id when creating new note

I'm pretty new to Django, I've been stuck on this view for a little while. My goal with this form is to be able to create a small note on a "Property" about maintenance or other information. The note would log the time, date, note and the user that recorded the note. Any help would be appreciated.
View:
#login_required(login_url="login")
def createNote(request, pk):
PropertyNoteFormSet = inlineformset_factory(
Property, PropertyNote, fields=('note', 'user',))
property_note = Property.objects.get(id=pk)
form = PropertyNoteFormSet(instance=property_note)
# form = OrderForm(initial={'customer': customer})
if request.method == "POST":
print(request.POST)
form = PropertyNoteFormSet(
request.POST, instance=property_note)
if form.is_valid():
form.save()
return redirect("/")
context = {"form": form}
return render(request, "dashboard/create_note.html", context)
Here is the ModelForm:
class PropertyNoteForm(ModelForm):
class Meta:
model = PropertyNote
fields = ['note']
exclude = ['user']
Here is the Model:
class PropertyNote(models.Model):
airbnb_name = models.ForeignKey(Property, blank=True,
null=True,on_delete=models.CASCADE)
note = models.TextField(blank=True, null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.note
The form comes out with around 4 boxes to fill in. Currently it works, but you have to actually select the user that is posting the note, I would like this part to be handled automatically and use the current logged in user. I think I still have a whole lot of holes in my knowledge around this stuff, I just can't seem to work it out.
Thanks in advance.
Edit:
I've tried this:
def createNote(request, pk):
PropertyNoteFormSet = inlineformset_factory(
Property, PropertyNote, fields=('note',), extra=1)
property_note = Property.objects.get(id=pk)
form = PropertyNoteFormSet(
queryset=PropertyNote.objects.none(), instance=property_note)
# form = OrderForm(initial={'customer': customer})
if request.method == "POST":
print(request.POST)
form = PropertyNoteFormSet(
request.POST, instance=property_note)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
print(instance.user)
instance.save()
return redirect("/")
context = {
"form": form,
'pk': pk,
}
return render(request, "dashboard/create_note.html", context)
But I get this:
AttributeError at /create_note/75/
'list' object has no attribute 'user'
Request Method: POST
Request URL: http://127.0.0.1:8000/create_note/75/
Django Version: 3.0.4
Exception Type: AttributeError
Exception Value:
'list' object has no attribute 'user'
you can use request.user.id to get the logged user id in your view.
See Documentation in Django
#login_required(login_url="login")
def createNote(request, pk, **kwargs):
note_form = PropertyNoteForm()
if request.method == "POST":
note_form = PropertyNoteForm(request.POST)
if note_form.is_valid():
add_note = note_form.save(commit=False)
add_note.user = request.user
add_note.airbnb_name =
Property.objects.get(id=pk)
add_note.save()
return redirect('/property/' + pk + '/')
context = {
"form": note_form,
'pk': pk,
}
return render(request, "dashboard/create_note.html", context)
I solved it with the above code. Using instance was the incorrect thing to do here. I didn't need to create an instance and I didn't need the inline form. I simply needed a new form:
note_form = PropertyNoteForm()
The user input information, I need to send that information to check if it's valid:
if request.method == "POST":
note_form = PropertyNoteForm(request.POST)
if note_form.is_valid():
Then I needed to populate the form with information that was not already in the form from the user:
add_note = note_form.save(commit=False)
add_note.user = request.user
add_note.airbnb_name = Property.objects.get(id=pk)
add_note.save()
return redirect('/property/' + pk + '/')

How to save to a database on click

In my previous question, I recently asked how to make forms.py in Django 1.9 show in HTML. now that this is done im trying to make a button which when the selection has been made (in this case it's radiobuttons) it will post to the database and move on with the questionaire.
Currently im attempting to make it post in my views.py but im having no luck in making it send the data.
def question1(request):
question_form = QuestionForm()
if request.method == 'POST':
form = QuestionForm(request.POST)
if form.is_valid():
return render(request, 'music.questions2,html')
return render(request, 'music/question1.html', locals())
Would really appreciate the help in making this happen.
def question1(request):
question_form = QuestionForm()
if request.method == 'POST':
form = QuestionForm(request.POST)
if form.is_valid():
form.save() # save to db!
return render(request, 'music.questions2,html')
return render(request, 'music/question1.html', locals())
# models.py
class Question(models.Model):
# Q_CHOICES is the previous declared one
question = models.CharField(max_length=20, choices=Q_CHOICES)
# forms.py
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['question']
widgets = {
'question': forms.RadioSelect()
}
Use: form.save()
def question1(request):
if request.method == 'POST':
form = QuestionForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'music.questions2,html')
else:
form = QuestionForm()
return render(request, 'music/question1.html', locals())

Categories