Trigger if form has change. Django - django

I have a trouble working on a ticketing system. Users create a ticket and get the information sent to their email. How can I send new information when a ticket gets changed from the admin panel?
model:
class TroubleTicket(models.Model):
title = models.CharField(max_length=200)
name = models.CharField(max_length=200)
address = models.CharField(choices=ADDRESSES, default=None,
max_length=200)
room = models.CharField(max_length=50)
message = RichTextUploadingField()
state = models.CharField(choices=STATES, max_length=30,
default='New')
answer = RichTextUploadingField(blank=True, null=True)
email = models.CharField(max_length=200, blank=True, null=True)
create_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('ticket_detail', kwargs={'pk': self.id})
class Meta:
ordering = ['-create_date']
save form and sending a message if the user specified a mail:
class CreateTicket(CreateView):
template_name = 'incidentjournal/add_ticket.html'
form_class = TicketForm
model = TroubleTicket
context_object_name = 'ticket'
success_url = reverse_lazy('home')
def form_valid(self, form):
recipient = form.cleaned_data['email'].encode('utf8')
new_ticket = form.save()
new_ticket_id = new_ticket.pk
address = new_ticket.address.encode('utf8')
title = new_ticket.title.encode('utf8')
name = new_ticket.name.encode('utf8')
room = new_ticket.room.encode('utf8')
send_to_email(recipient, str(new_ticket_id), title, address,
room, name)
send_to_bot(str(new_ticket_id), title, address, room, name)
return super(CreateTicket, self, ).form_valid(form)
If the state or the answer has been changed in the admin panel I want to send the changes to the user.
Thanks for your advice.

Related

Delete a user from a room Django

In my app, I have created rooms where participants(users) can message.
In models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Topic(models.Model):
name = models.CharField(max_length=200)
def __str__(self) :
return self.name
class Room(models.Model):
host = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
topic = models.ForeignKey(Topic, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
participants = models.ManyToManyField(User, related_name='participants', blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-updated', '-created']
def __str__(self):
return self.name
class Message(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE)
body = models.TextField()
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.body[0:50]
Now, in the participants section, I have added a user whenever the user sends a message sends a message for the first time in that room.
In views.py
def room(request, pk):
room = Room.objects.get(id=pk)
room_messages = room.message_set.all().order_by('-created')
participants = room.participants.all()
print(participants.all())
if request.method == 'POST':
message = Message.objects.create(
user=request.user,
room=room,
body=request.POST.get('body')
)
room.participants.add(request.user)
return redirect('room', pk=room.id)
context = {'room':room, 'room_messages':room_messages,
'participants':participants}
return render(request, 'base/room.html', context)
Now I want to delete a user from participants when that user deletes all his messages from the room. I am not getting an idea how to proceed here.
In views.py
#login_required(login_url='login')
def deleteMessage(request, pk):
message = Message.objects.get(id=pk)
room = Room.objects.get(id=pk)
room_messages = Message.objects.filter(room=room)
if request.user != message.user:
return HttpResponse('You are not allowed here!')
if request.method == 'POST':
message.delete()
return redirect('home')
return render(request, 'base/delete.html', {'obj':message})
How can I do this?
participants = models.ManyToManyField(User, related_name='participants', blank=True)
The related_name here should be rooms, and not participants. This is a pretty common mistake. Although in this case it doesn't affect you.
Now for your problem, you have the Room instance and the User instance, so you can query the Message table and if there are no messages with that User and Room instance combo you can safely remove the user from the room.
messages = Message.objects.filter(room=room, user=request.user).count()
if not messages:
room.participants.remove(request.user)

Autofilling Django model form field with data from associated objects

I have a model form that creates a new job entry, and on submission, I need an invisible field job_time_estimation to be set to a sum of 'service_stats_estimate_duration' values from ServiceItemStats objects associated with the JobEntry by a many-to-many relationship when submitting the form.
For example, if in my NewJobEntryForm I chose two existing ServiceItemStats objects that have service_stats_estimate_duration values 60 and 90, on submission, I want a value 150 to be saved in that JobEntry object's job_time_estimation attribute.
I tried doing this using aggregation by defining a save() method in the model but I am getting an error "name 'serviceItemStats' is not defined".
I am not sure if I am going about this the right way. Any help would be appreciated.
My code:
models.py:
class ServiceItemStats(models.Model):
service_stats_name = models.CharField(primary_key=True, max_length=20)
service_stats_estimate_duration = models.IntegerField()
# Many-to-many relationship with JobEntry.
def __str__(self):
return self.service_stats_name
class JobEntry(models.Model):
# PK: id - automatically assigned by Django.
jo
b_entry_date_time = models.DateTimeField(default=timezone.now)
jo
b_date = models.DateField(blank=True, null=True)
job_checked_in = models.BooleanField()
job_checked_out = models.BooleanField(default=False)
job_priority = models.IntegerField()
job_time_estimation = models.IntegerField(blank=True, null=True)
job_comments = models.TextField(max_length=200, blank=True, null=True)
job_parts_instock = models.BooleanField(default=False)
job_started = models.BooleanField(default=False)
job_finished = models.BooleanField(default=False)
job_expand_fault_evidence = models.ImageField(blank=True, null=True)
job_expand_comments = models.ImageField(blank=True, null=True)
job_expand_parts_required = models.CharField(max_length=200, blank=True, null=True)
vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE) #One-to-one relationship
customer = models.ForeignKey(Customer, on_delete=models.CASCADE) #One-to-one relationship
serviceBay = models.ForeignKey(ServiceBay, on_delete=models.CASCADE, blank=True, null=True) #One-to-one relationship
serviceItemStats = models.ManyToManyField(ServiceItemStats, blank=True) #Many-to-many relationship
def __str__(self):
return self.id
def save(self, *args, **kwargs):
if not self.job_time_estimation:
self.job_time_estimation = serviceItemStats.objects.all().aggregate('service_stats_estimate_duration')
return super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("jobs:job_detail",kwargs={'pk':self.pk})
views.py
class JobCreateView(FormView):
template_name = "jobs/jobentry_form.html"
form_class = NewJobEntryForm
success_url = reverse_lazy("jobs:job_list")
def form_valid(self, form):
form.save()
return super(job_list, self).form_valid(form)
forms.py
class NewJobEntryForm(ModelForm):
class Meta:
model = JobEntry
fields = ['vehicle', 'customer', 'job_date', 'job_checked_in', 'job_priority', 'job_comments', 'job_parts_instock', 'serviceItemStats']
widgets = {
'job_date' : forms.DateInput(format=('%m/%d/%Y'), attrs={'class':'form-control', 'placeholder':'Select a date', 'type':'date'}),
'ServiceItemStats' : forms.CheckboxSelectMultiple(),
'job_priority' : forms.RadioSelect(choices=priorityOptions),
}
You can try this.
from django.db.models import Sum
class JobCreateView(FormView):
template_name = "jobs/jobentry_form.html"
form_class = NewJobEntryForm
success_url = reverse_lazy("jobs:job_list")
def form_valid(self, form):
job=form.save()
estimation = job.serviceItemStats.all().aggregate(total=Sum('service_stats_estimate_duration'))
job.job_time_estimation = estimation['total']
job.save()
return super(job_list, self).form_valid(form)

foreign key in django

I have a model for musics and a model for comment of musics:
class music(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
STATUS_CHOICES = (('draft', 'Draft'), ('published', 'Published'),)
music = models.FileField()
music_image = models.ImageField(upload_to="images/")
singer_name = models.CharField(max_length=100)
music_name = models.CharField(max_length=100)
text_of_music = models.TextField()
create = models.DateField(auto_now_add=True, blank=True, null=True)
update = models.DateField(auto_now=True, blank=True, null=True)
publish = models.DateField(default=timezone.now, blank=True, null=True)
slug = models.CharField(max_length=250, unique_for_date='publish')
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
objects = models.Manager()
published = PublishedManager()
class Meta:
ordering = ('-publish',)
def get_absolute_url(self):
return reverse('music:music_detail',
kwargs={"id":self.id})
class comment(models.Model):
# Foreignkey for each music
For = models.ForeignKey(music, on_delete=models.CASCADE, related_name='post')
body = models.CharField(max_length=500)
created_on = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
commented_by = models.ForeignKey(User, on_delete=models.CASCADE)
and this is my view:
def music_Detail(request, id=None):
user = request.user
template_name = 'music/music_detail.html'
Music = music.objects.all().filter(id=id)
new_comment = None
Comment = comment.objects.all().filter(active=True)
form = comment_form(data=request.POST)
if request.method == 'POST':
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.For = Music
new_comment.save()
form = comment_form()
return render(request, template_name, {'Music': Music, 'Comment': Comment, 'form': form})
Well, I get this error when I comment:
Cannot assign "<QuerySet [<music: m, majid kharatha>]>": "comment.For" must be a "music" instance.
How can I solve this problem and how can I display the information of the user who left this comment?
As the error says, you'll have to assign a single Music, not a queryset.
Instead of filter()ing to get a new queryset containing a single music,
Music = music.objects.all().filter(id=id)
you want to get() a single one:
Music = music.objects.get(id=id)

Django forms. TypeError: __init__() got an unexpected keyword argument 'instance'

I keep getting error messages and have no idea why. I think it has to do with the variable for instance, but i see a lot of examples all over the internet that work the same way.
models.py
class Establishments(models.Model):
title = models.CharField(max_length=255)
town = models.ForeignKey(Town, on_delete=SET_NULL, null=True)
addrstreet = models.CharField(max_length=255)
addrzip = models.CharField(max_length=12)
telephone = models.CharField(max_length=15)
email = models.CharField(max_length=255)
chamberofcomnr = models.CharField(max_length=25)
description = models.TextField(max_length=255)
website = models.CharField(max_length=255)
categorie = models.ForeignKey(Establishmentcategory, on_delete=SET_NULL, null=True)
pub_date = models.DateTimeField('date published')
drupuser = models.ForeignKey(Drupalusers, on_delete=SET_NULL, null=True)
druppublished = models.BooleanField()
drupurl = models.CharField(max_length=255)
drupnodeid = models.IntegerField()
def __str__(self):
return self.title
class Impcalendar(models.Model):
establishment = models.ForeignKey(Establishments, on_delete=SET_NULL, null=True)
active = models.BooleanField()
prio = models.IntegerField()
url = models.CharField(max_length=255)
check_intervalh = models.IntegerField()
check_fixedh = models.IntegerField()
log = models.BooleanField()
cuttag = models.CharField(max_length=255)
cuttxt = models.CharField(max_length=255)
cuttxtend = models.CharField(max_length=255)
comment = models.CharField(max_length=255)
page = models.TextField()
pageold = models.TextField()
change = models.TextField()
pagedate = models.DateTimeField()
pagedatenext = models.DateTimeField()
status = models.IntegerField()
errors = models.IntegerField()
def __str__(self):
return str(self.id)
urls.py
path('calendar/<int:calendar_id>/', views.calendaredit, name='calendaredit')
views.py
def calendaredit(request, calendar_id):
calendar = get_object_or_404(Impcalendar, pk=calendar_id)
print (calendar.url)
form = ImpcalendarForm(request.POST or None, instance=calendar)
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
print (form.url)
# check whether it's valid:
if form.is_valid():
#calendar.establishment = form.cleaned_data['
calendar = form.save(commit=false)
calendar.active = form.cleaned_data['active']
calendar.save()
return redirect('handmatig')
return render(request, 'import_calendar/handmatig_edit.html', {'form': form})
forms.py
class ImpcalendarForm(forms.Form):
establishment = forms.ModelChoiceField(queryset = Establishments.objects.all())
page = forms.CharField(widget=forms.Textarea)
pageold = forms.CharField(widget=forms.Textarea)
change = forms.CharField(widget=forms.Textarea)
class Meta:
model = Impcalendar
fields = '__all__'
So i want to have a record page, listing all the records already works, where i can edit the form. It needs to show the record as a Django form. It crashes on the line;
form = ImpcalendarForm(request.POST or None, instance=calendar)
If i print the variable calendar or calendar.url i get the correct data.
The error message is;
TypeError: __init__() got an unexpected keyword argument 'instance'
Spend a week debugging. Now escalading. ;-)
Your form subclasses forms.Form instead of forms.ModelForm.
Normal forms don't take model instances, and neither do they have an inner Meta class.

How to count users posts in Django?

In a simple forum app in Django, on each thread I want to render posts by several users on the same page (on a user panel at the user's post, like all conventional forums).
Here are the models:
class Post(models.Model):
title = models.CharField(max_length=75, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
updated = models.DateTimeField(auto_now=True)
topic = models.ForeignKey(Topic)
body = models.TextField(max_length=10000)
class Topic(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(max_length=10000, null=True)
forum = models.ForeignKey(Forum)
created = models.DateTimeField()
creator = models.ForeignKey(User, blank=True, null=True)
updated = models.DateTimeField(auto_now=True)
closed = models.BooleanField(blank=True, default=False)
published = models.BooleanField(blank=True, default=False)
visits = models.IntegerField(default = 0)
weight = models.IntegerField(blank=True, default=0)
slug = models.CharField(max_length=100, blank=True)
def num_posts(self):
return self.post_set.count()
def num_replies(self):
return max(0, self.post_set.count() - 1)
def last_post(self):
if self.post_set.count():
return self.post_set.order_by("-created")[0]
def __unicode__(self):
return unicode(self.creator) + " - " + self.title
def save(self, *args, **kwargs):
super(Topic, self).save(*args, **kwargs)
I have also this wierd model:
class PostCount(models.Model):
user = models.OneToOneField(User)
posts = models.IntegerField(default=0)
#classmethod
def create(cls, user):
postcount = cls(user=user)
return postcount
Which somehow magically returns number of topics by a user (not number of posts) so that they can be accessed in the template using {{topic.creator.postcount.posts}}.
And the view that render topics:
def topic(request, topic_id):
"""Listing of posts in a topic."""
posts = Post.objects.filter(topic=topic_id).order_by("created")
posts = mk_paginator(request, posts, DJANGO_SIMPLE_FORUM_REPLIES_PER_PAGE)
topic = Topic.objects.get(pk=topic_id)
topic.visits += 1
topic.save()
forum = topic.forum
return render_to_response("myforum/topic.html", add_csrf(request, posts=posts, pk=topic_id,
topic=topic, forum= forum), context_instance=RequestContext(request))
So I'm wondering how best to have number of posts by a user in template?
Do you not want to use the built in count, because that would solve your problem.
views.py- should get all the users, if you wanted a selected user group per se you would just use filter
context = {}
post_numbers = Post.objects.all().count()
context['post_numbers'] = post_numbers
Template
{{ post_numbers }}