I trial make Notification for Comment
by Many-to-many relationships
how fix it
raise TypeError(
TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use NotfFaId.set() instead.
[17/Apr/2021 03:37:31] "POST /forum/addcomment/ HTTP/1.1" 500 73061
class CommentT(MPTTModel):
Topic = models.ForeignKey(Topic, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey( User, on_delete=models.CASCADE, related_name='author')
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
NotfFaId = models.ManyToManyField( User, related_name='NotfFaVId', default=None, blank=True)
content = models.TextField()
publish = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=True)
class MPTTMeta:
order_insertion_by = ['publish']
def addcomment(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = CommentT.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = NewCommentTForm(request.POST)
# print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
result = comment_form.cleaned_data.get('content')
user = request.user.username
user_comment.author = request.user
user_comment.NotfFaId = request.user
user_comment.save()
Topic.objects.get(id = request.POST.get('Topic') ).NotfFaV.add(request.user)
# CommentT.objects.get(id=user_comment.id).NotfFaId.add(request.user)
return JsonResponse({'result': result, 'user': user,'id': user_comment.id })
don't work ,
raise ValueError('"%r" needs to have a value for field "%s" before '
ValueError: "<CommentT: CommentT object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used.
def addcomment(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = CommentT.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = NewCommentTForm(request.POST)
# print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
result = comment_form.cleaned_data.get('content')
user = request.user.username
user_comment.author = request.user
user_comment.NotfFaId.set( request.user )
user_comment.save()
Topic.objects.get(id = request.POST.get('Topic') ).NotfFaV.add(request.user)
return JsonResponse({'result': result, 'user': user,'id': user_comment.id })
thank Iain Shelvington,
it is word
I Called CommentT.objects.get(id=user_comment.id).NotfFaId.add(request.user) after user_comment.save(). You can't add many to many entries before you have saved both sides of the relationship – Iain Shelvington 2 hours ago
def addcomment(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = CommentT.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = NewCommentTForm(request.POST)
# print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
result = comment_form.cleaned_data.get('content')
user = request.user.username
user_comment.author = request.user
# user_comment.NotfFaId.set( request.user )
user_comment.save()
Topic.objects.get(id = request.POST.get('Topic') ).NotfFaV.add(request.user)
CommentT.objects.get(id=user_comment.id).NotfFaId.add(request.user)
return JsonResponse({'result': result, 'user': user,'id': user_comment.id })
Related
I'm working on this project but I got the following error
comm = doctor_detail.comments.filter(active=True)
AttributeError: 'Doctor' object has no attribute 'comments' however I think that everything is alright
this is my models.py
class Comments(models.Model):
co_name = models.CharField(max_length=50, verbose_name="الاسم ")
co_email = models.EmailField(
max_length=50, verbose_name="البريد الالكتروني")
co_body = models.TextField(max_length=400, verbose_name='التعليق')
created_dt = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
post = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='comments')
def __str__(self):
return 'علق {} على {}'.format(self.co_name, self.post)
this is my views.py
def doctor_detail(request, slug):
# استدعاء جميع البينات اللي في البروفايل
doctor_detail = get_object_or_404(Doctor, slug=slug)
comm = doctor_detail.comments.filter(active=True)
form = Commentair()
if request.method == 'POST':
form = Commentair(data=request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.post = doctor_detail
new_comment.save()
form = Commentair()
else:
form = Commentair()
return render(request, 'user/doctor_detail.html', {'doctor_detail': doctor_detail,
'comm': comm,'form': form
})
I really don't know why I'm facing this error because the related name is available and I think everything is okay .please if there is an answer to this write it and explain it to me. thank you
### You done mistake in here comments -> Comments c will be capital in filter
def doctor_detail(request, slug):
# استدعاء جميع البينات اللي في البروفايل
doctor_detail = get_object_or_404(Doctor, slug=slug)
comm = doctor_detail.Comments.filter(active=True)
form = Commentair()
if request.method == 'POST':
form = Commentair(data=request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.post = doctor_detail
new_comment.save()
form = Commentair()
else:
form = Commentair()
return render(request, 'user/doctor_detail.html', {'doctor_detail': doctor_detail,
'comm': comm,'form': form
})
I have a checkbox on my django app, where user can add or remove a listing from their watchlist.
However, this checkbox always returns False, and is never in request.POST, i have tried sooo many solutions from SO and all over the internet for literal days now and cant figure it out
Models.py
class Watchlists(models.Model):
user = models.CharField(max_length=64, default='user')
title = models.CharField(max_length=64, blank=True)
watchlist = models.BooleanField(default=False, blank=False)
def __str__(self):
return f"{self.title}, {self.user}, {self.watchlist}"
Forms.py
class CheckForm(ModelForm):
watchlist = forms.BooleanField(required=False)
# watchlist = forms.DecimalField(widget=forms.CheckboxInput(attrs={"value":"watchlist"}))
class Meta:
model = Watchlists
fields = ['watchlist']
Checkbox didnt have a value so i thought that was the issue and tried to give it one here on the commented line, it didnt help
Views.py
watchlist = CheckForm(request.POST or None)
if request.method == 'POST':
# if request.POST['watchlist']:
# if 'watchlist' in request.POST:
# if request.POST.get('watchlist', False):
if request.POST.get('watchlist', '') == 'on':
if watchlist.is_valid():
check = watchlist.cleaned_data['watchlist']
watchlist_data = Watchlists.objects.all().filter(title=title, user=username).first()
if not watchlist_data:
watchlisted = Watchlists.objects.create(title=title, user=username, watchlist='True')
watchlisted.save()
if watchlist_data:
watchlist_data.delete()
I have tried all the different solutions i could find
**Template**
<form action="listing" method="POST">
{% csrf_token %}
{{ checkbox }}
</form>
It has a name and id attribute, label is fine too
**Entire views.py**
#login_required
def listing(request, title):
if request.user.is_authenticated:
username = request.user.get_username()
form = BidForm()
comment_form = CommentForm()
watchlist = CheckForm(request.POST or None)
listing_object = Listing.objects.all().filter(title=title).first()
author = listing_object.user
bids = Bid.objects.all().filter(title=title).values_list("price", flat=True)
max_bid = max(bids, default=0)
comments = Comment.objects.all().filter(list_title=title)
if request.method == "POST":
bid = Bid(title=title, user=username)
bidform = BidForm(request.POST, request.FILES, instance=bid)
# if request.POST['watchlist']:
# if 'watchlist' in request.POST:
# if request.POST.get('watchlist', False):
if request.POST.get('watchlist', '') == 'on':
if watchlist.is_valid():
check = watchlist.cleaned_data['watchlist']
watchlist_data = Watchlists.objects.all().filter(title=title, user=username).first()
if not watchlist_data:
watchlisted = Watchlists.objects.create(title=title, user=username, watchlist='True')
watchlisted.save()
if watchlist_data:
watchlist_data.delete()
if "price" in request.POST:
if bidform.is_valid():
price = bid.price
if not bids:
bid = bidform.save()
messages.success(request, 'Your bid has been placed succesfully')
return HttpResponseRedirect(reverse('listing', args=(), kwargs={'title': title}))
else:
max_bid = max(bids)
if price >= listing_object.price and price > max_bid:
bid = bidform.save()
messages.success(request, 'Your bid has been placed succesfully')
return HttpResponseRedirect(reverse('listing', args=(), kwargs={'title': title}))
else:
messages.warning(request, 'Bid price must be greater than highest bid and starting price')
return HttpResponseRedirect(reverse('listing', args=(), kwargs={'title': title}))
if "close" in request.POST:
bid = Bid.objects.all().filter(title=title, price=max_bid).first()
max_bid_user = bid.user
listing_object.tag = 'closed'
listing_object.save()
if username == max_bid_user:
messages.warning(request, 'Thank you for your entry into this auction. You have emerged the winner and this listing has been closed')
return HttpResponseRedirect(reverse('listing', args=(), kwargs={'title': title}))
comment = Comment(user_commented=username, list_title=title, list_author=author)
comment_form = CommentForm(request.POST, request.FILES, instance=comment)
if "comment" in request.POST:
if comment_form.is_valid():
user_comment = comment_form.save()
comments = Comment.objects.all().filter(list_title=title)
return HttpResponseRedirect(reverse('listing', args=(), kwargs={'title': title}))
return render(request, "auctions/listing.html", {
"form": form,
"listing": listing_object,
"checkbox": watchlist,
"max_bid": max_bid,
"users": author,
"commentform": comment_form,
"comments": comments
})
urls.py
path("auctions/<str:title>/", views.listing, name="listing"),
First, you don't have to add blank=False in your watchlist field since you gave it a default value, so rewrite it like so
watchlist = models.BooleanField(default=False)
By doing so, you can also remove this from your forms.py. It's not necessary
watchlist = forms.BooleanField(required=False)
Just use as follows
class CheckForm(ModelForm):
class Meta:
model = Watchlists
fields = ['watchlist']
Additional things to fix based on #Sunderam Dubey's comment
In your HTML form, change action="listing" to action="{% url 'listing' %}"
I am currently making a flashcard web application with Django.
There is a 'set' page (dashboard) and a 'card' page (set-edit). When I fill in and submit the form on the card page (set-edit) to add a new card to the set which has been selected for editing, I received a value error ' Cannot assign "2": "Card.set" must be a "Set" instance.'
I'm unsure why this is happening because there is an instance of Set with an id of 2.
Any suggestions of how to rectify this issue?
views.py
###################
##Dashboard views##
###################
def dashboard(request):
set = Set.objects.all()
set_count = set.count()
if request.method == 'POST':
form = SetForm(request.POST)
if form.is_valid():
form.save()
set_name = form.cleaned_data.get('name')
messages.success(request, f'{set_name} has been added')
return redirect('dashboard-dashboard')
else:
form = SetForm()
context = {
'set': set,
'form': form,
}
return render(request, 'dashboard/dashboard.html', context)
#############
##Set views##
#############
#Cards is for when you are adding cards to a set or looking at the content of a set
def set_edit(request, pk):
set_title = Set.objects.get(id=pk)
card = Set.objects.get(id=pk).card_set.all()
set_id = pk
set = Set.objects.get(id=pk)
if request.method == 'POST':
form = CardForm(request.POST)
print('Entered Post condition')
if form.is_valid():
obj = form.save(commit=False)
obj.set = pk
obj.save()
card_name = form.cleaned_data.get('kanji')
messages.success(request, f'{card_name} has been added')
return redirect('dashboard-set-edit',pk)
else:
form = CardForm()
context = {
'card': card,
'form': form,
}
return render(request, 'dashboard/set_edit.html', context)
```
**models.py**
```
class Set(models.Model):
name = models.CharField(max_length=100, null=True)
quantity = models.PositiveIntegerField(null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.id}'
class Card(models.Model):
kanji = models.CharField(max_length=100, null=True)
kana = models.CharField(max_length=100, null=True)
english = models.CharField(max_length=100, null=True)
set = models.ForeignKey(Set, on_delete=models.CASCADE,default=3)
def __str__(self):
return f'{self.id}'
```
**forms.py**
```
class CardForm(forms.ModelForm):
class Meta:
model = Card
# fields = '__all__'
exclude = ('set',)
class SetForm(forms.ModelForm):
class Meta:
model = Set
fields = '__all__'
```
**urls.py**
urlpatterns = [
#########
##Sets###
#########
path('sets/edit/<int:pk>/', views.set_edit,
name='dashboard-set-edit'),
path('sets/delete/<int:pk>/', views.set_delete,
name='dashboard-set-delete'),
#########
##Cards##
#########
path('card/delete/<int:pk>/', views.card_delete,
name='dashboard-cards-delete'),
path('cards/detail/<int:pk>/', views.card_detail,
name='dashboard-cards-detail'),
path('cards/edit/<int:pk>/', views.card_edit,
name='dashboard-cards-edit'),
#############
##Dashboard##
#############
path('dashboard/', views.dashboard, name='dashboard-dashboard'),
]
```
You should assign it to .set_id, not .set:
if form.is_valid():
# use set_id ↓
form.instance.set_id = pk
obj = form.save()
card_name = form.cleaned_data.get('kanji')
messages.success(request, f'{card_name} has been added')
return redirect('dashboard-set-edit',pk)
i have a form with a google map and when the user does not click on the map i need to send latitude and longitude as None to views.py ,this is views.py :
if request.method == "POST":
if request.user.is_authenticated:
if True:
form = CreatMeetingForm(request.POST,request.FILES)
print(request.POST)
if form.is_valid():
if 'id' in request.POST:
obj= get_object_or_404(Meeting, id=request.POST.get('id'))
form = CreatMeetingForm(request.POST or None,request.FILES or None, instance= obj)
meeting= form.save(commit= False)
members = form.cleaned_data['members_email']
try:
meeting.lat= round(form.cleaned_data['lat'],14)
meeting.lng = round(form.cleaned_data['lng'],14)
except :
meeting.lat= None
meeting.lng = None
meeting.host = request.user
update = True
meeting.save()
else :
meeting=form.save(commit=False)
members = form.cleaned_data['members_email']
try:
meeting.lat= round(form.cleaned_data['lat'],14)
meeting.lng = round(form.cleaned_data['lng'],14)
except :
meeting.lat= None
meeting.lng = None
meeting.host = request.user
update=False
meeting.save()
else:
print('form not valid')
form.errors["code"] = 0
return JsonResponse(form.errors)
else:
return HttpResponse('Unauthorized', status=401)
and this is my model fields:
lat = models.DecimalField(max_digits=19, decimal_places=16,blank=True,null=True)
lng = models.DecimalField(max_digits=19, decimal_places=16,blank=True,null=True)
when i want to create a new form my code works but when in edit mode and i send the id in requet.POST it raises this error:
{"lat": ["Enter a number."], "lng": ["Enter a number."], "code": 0}
it seems i get the error in form.is_valid bcs i can see the print('form not valid')
any suggestion?
It might help to add the default value to the field definitions like so:
lat = models.DecimalField(
max_digits=19,
decimal_places=16,
blank=True,
null=True,
default=None
)
lng = models.DecimalField(
max_digits=19,
decimal_places=16,
blank=True,
null=True,
default=None
)
Edit: If this doesn't help, please share the definition of CreatMeetingForm.
Please Help!
I am trying to update a group of formsets that are related the main form (Project Information) by the main forms pk. The create form works fine, but I am finding it extremely difficult to implement the update version.
It's the save as an update part that I can't figure out for the formsets. The main form updates the database correctly. The formsets just create new records instead of updating the existing ones. I do not know how to instance the formsets.
Here the code.
view.py
#login_required
def edit_project(request):
SampleInformationFormSet = formset_factory(SampleInformationForm, extra=1)
DissolutionMethodsFormSet = formset_factory(DissolutionMethodsForm, extra=1)
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
if request.method == 'POST':
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
pi_pk = ''
p = ''
if form.is_valid():
pi_pk = form.cleaned_data['hd']
p = ProjectInformation.objects.get(pk=pi_pk)
form = ProjectInformationForm(request.POST, instance=p)
form.save() # This form saves correctly
for si_form in si_formset:
si_form.save() # I do not know how to attach an instance to these formsets
for d_form in d_formset:
d_form.save()
messages.success(request, 'Your project has been updated!')
return redirect('edit_project')
else:
pass
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
messages.warning(request, 'There was an error saving your form.')
study_id_select = list(
ProjectInformation.objects.values('dissolution_study_id', 'id').filter())
context = {'form': form, 'si_formset': si_formset, 'd_formset': d_formset, 'study_id_select': study_id_select}
return render(request, 'main/edit_project.html', context)
models.py I'm just going to include part of three of the seven models to keep this a little shorter.
class ProjectInformation(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
compound_code = models.CharField(max_length=60)
product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
main_component = models.CharField(max_length=100)
class SampleInformation(models.Model):
sample_index = models.CharField(max_length=30)
sample_type_purpose = models.ForeignKey(SampleTypePurpose, on_delete=models.CASCADE)
specification_number = models.CharField(max_length=20, blank=True, null=True)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE, blank=True, null=True)
class DissolutionMethods(models.Model):
number_of_methods = models.IntegerField(default=1,
validators=[MaxValueValidator(10), MinValueValidator(1)],
blank=True, null=True)
dissolution_method_index = models.CharField(max_length=10)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE, blank=True, null=True)
forms.py
class ProjectInformationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['hd'] = forms.CharField(widget=forms.HiddenInput, required=False)
class Meta:
model = ProjectInformation
fields = '__all__'
class SampleInformationForm(forms.ModelForm):
class Meta:
model = SampleInformation
fields = '__all__'
Please help if you can. This project has been a trial by fire and the flames are hot!
Finally solved it myself.
#login_required
def edit_project(request):
SampleInformationFormSet = formset_factory(SampleInformationForm, extra=1)
DissolutionMethodsFormSet = formset_factory(DissolutionMethodsForm, extra=1)
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
if request.method == 'POST':
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
pi_pk = ''
p = ''
if form.is_valid():
pi_pk = form.cleaned_data['hd']
p = ProjectInformation.objects.get(pk=pi_pk)
form = ProjectInformationForm(request.POST, instance=p)
form.save()
si = p.sampleinformation_set.all() # All the Methods related to the instance
d = p.dissolutionmethods_set.all()
si_cnt = 0
for si_form in si_formset:
if si_form.is_valid():
update = si_form.save(commit=False)
update.pk = si[si_cnt].pk
update.save()
si_cnt += 1
d_cnt = 0
for d_form in d_formset:
if d_form.is_valid():
update = d_form.save(commit=False)
update.pk = d[d_cnt].pk
update.save()
d_cnt += 1