I'm trying to implement a draft function on my simple message application which using a custom UserModel
A draft function is when the user doesn't send the mail straight away but saves it.
I'm having trouble figuring out how can I implement a draft function using my model.
I am able to figure out how to send a mail.
#login_required
def Create(request):
person = Person.objects.get(user=request.user)
form = NewMessageForm()
if request.POST.get('send', False):
form = NewMessageForm(request.POST)
if form.is_valid():
recipient = form.cleaned_data['recipient']
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
thread = Thread.objects.create(subject=subject,user=request.user)
recipient = User.objects.get(username=recipient)
message = Message.objects.create(user=request.user,recipient=recipient,body=message,thread=thread)
return HttpResponseRedirect(reverse('world:message'))
elif request.POST.get('save', False):
#How can I save it as a draft?
return render(request,'create.html',{'messages':messages,'form':form,'person':person})
models
class Thread(models.Model):
subject = models.CharField(max_length=100, blank=True)
user = models.ForeignKey(User)
class Message(models.Model):
user = models.ForeignKey(User, related_name='sender')
recipient = models.ForeignKey(User, related_name='recipient')
created = models.DateTimeField(auto_now_add=True)
body = models.CharField(max_length=1000)
read = models.BooleanField(default=False)
trash = models.BooleanField(default=False)
sentmessage = models.BooleanField(default=False)
thread = models.ForeignKey(Thread)
def __unicode__(self):
return self.body
forms
class NewMessageForm(forms.ModelForm):
recipient = forms.CharField(required=True,max_length=1)
message = forms.CharField(widget=forms.Textarea,required=True,max_length=1)
checkbox = forms.BooleanField(required=False)
def clean_recipient(self):
recipient = self.cleaned_data['recipient']
try:
recipient = User.objects.get(username=recipient)
except User.DoesNotExist:
raise forms.ValidationError("This username does not exist")
return recipient
class Meta:
model = Thread
fields = ('subject',)
template
<form method="POST" >
{% csrf_token %}
{{form.recipient}}
{{form.subject}}
{{form.message}}
<input type="submit" value="send" name="_send" />
<input type="submit" value="save" name="_save" />
</form>
You could add a BooleanField "draft" in Message which determine if the current message is a draft or not and filter the mailbox by exclude every message with the state draft and where recipient = current_user.
This needs to modify a bit your logic by set draft to 0 when the message is sent, 1 when the message is save.
EDIT: I didn't see your messagesent attribute. You could use it for that comportement, I think it's appropriate :)
Related
I have a ModelChoiceField in a form that uses a TextInput widget. I want to be able to select a value from the database or add new entries to the database with this input. If the value is not already in the database, I get an error on the form that says "Select a valid choice. That choice is not one of the available choices."
Model
class FeedCategory(models.Model):
category = models.CharField(max_length=255, unique=True)
class RssFeed(models.Model):
category = models.ForeignKey(FeedCategory, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=255)
feed = models.URLField()
Form
class RssForm(forms.Form):
name = forms.CharField()
feed = forms.URLField()
category = forms.ModelChoiceField(queryset=FeedCategory.objects.all(), to_field_name='category', widget=forms.TextInput())
def clean(self):
cleaned_data = super().clean()
????
Views
class RssCreateView(FormView):
template_name = 'dashboard/rss_feed_form.html'
form_class = RssForm
success_url = '/dashboard/'
def form_valid(self, form):
name = form.cleaned_data['name']
feed = form.cleaned_data['feed']
category = form.cleaned_data['category']
rss_obj = RssFeed(category=category, name=name, feed=feed)
rss_obj.save()
return super().form_valid(form)
Template
<form method="post">
{%csrf_token%}
{{form|crispy}}
<button type="submit">Save</button>
</form>
It might help you what I am using:
category = models.ForeignKey("General.entity",verbose_name='Category', db_column="CategoryEntityRef", null=False, blank=False)
so, what I am doing with this is creating a field that points to an existing category that exists in another table. It will display it as a dropdown box. However using this method will allow me to have the option to add another Category:
I am trying to let a user create a "club" (basically a group) where the user later on can add users to.
Currently it does not create a field in the database somehow.
Any suggestions would be appreciated since I am fairly new to forms.
Model
class Club(models.Model):
owner = models.CharField(max_length=30)
topic = models.CharField(max_length=30)
start = models.DateTimeField(verbose_name='start date', auto_now_add=False)
end = models.DateTimeField(verbose_name='end date', auto_now_add=False)
account = models.ManyToManyField(Account)
Views
#login_required
def add_club(request):
if request.method == "POST":
form = AddClubForm(request.POST, instance=request.user)
print(form)
if form.is_valid():
form.save()
return HttpResponseRedirect(request.path_info)
else:
form = AddClubForm(instance=request.user)
return render(request, 'page/club.html', {
"form": form,
})
Form
class AddClubForm(forms.Model):
owner = forms.CharField(required=True)
topic = forms.CharField(required=False)
start = forms.DateField(required=False)
end = forms.DateField(required=False)
class Meta:
model = Club
fields = (
'owner',
'topic',
'start',
'end',
)
Template
<form method="POST" action="">
{% csrf_token %}
<div class="col-md-6">
<label class="labels">Create a club</label>
{{ form.owner }}
<input class="btn" type="submit" value="Add club">
</div>
</form>
Since this answered your problem, I am posting the solution here:
You need to add blank=True, null=True to your fields in your model, otherwise it expects them when saving the form.
class Club(models.Model):
owner = models.CharField(max_length=30)
topic = models.CharField(max_length=30, blank=True, null=True)
start = models.DateTimeField(verbose_name='start date', auto_now_add=False, blank=True, null=True)
end = models.DateTimeField(verbose_name='end date', auto_now_add=False, blank=True, null=True)
account = models.ManyToManyField(Account, blank=True)
Concerning the instance=request.user, I believe you misunderstanding the use of instance in a ModelForm.
If the request method is GET, the instance is used to populate a ModelForm with data from an existing Club object, and then pass it to your template to display the information.
If the request method is POST (or PUT), instance represent the existing Club object you want to update with data received from the form.
You usually need to use the instance arg in a DetailView (either to update or retrieve one specific Club), never when creating an object.
That's why you need to remove the instance arg in your views.py:
form = AddClubForm(request.POST)
I need to add data to the database For that, I'm trying some code. But I can't add foreignkey values. The code throws exceptions. Here are my views.py, models.py code and exceptions.
first try:
views.py
def notification(request):
user = request.user
if request.method == 'POST':
property_id = request.POST['property_id']
owner = request.POST['owner_id']
property_object = Property.objects.get(id=property_id)
owner_object = Property.objects.get(owner=owner)
notification = user, "have intrested in your property"
property_object.notify.add(user)
notifications = Notifications.objects.create(notification=notification, owner=owner_object
,property=property_object)
notifications.save()
it throws exception
ValueError: Field 'id' expected a number but got 'hafis'.
second try
views.py
def notification(request):
user = request.user
if request.method == 'POST':
property_id = request.POST['property_id']
owner = request.POST['owner_id']
property_object = Property.objects.get(id=property_id)
notification = user, "have intrested in your property"
property_object.notify.add(user)
notifications = Notifications.objects.create(notification=notification, owner=owner,
property=property_id)
notifications.save()
it throws exception
ValueError: Cannot assign "'hafis'": "Notifications.owner" must be a "User" instance.
models.py
class Property(models.Model):
owner = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
city = models.CharField(max_length=100)
location = models.CharField(max_length=100)
facilites = models.TextField()
rent = models.CharField(max_length=200)
images = models.FileField(upload_to='media/uploads',null=True)
email = models.EmailField()
mobile = models.IntegerField(null=True)
date = models.DateTimeField(auto_now_add=True)
notify = models.ManyToManyField(User, default=None, blank=True, related_name='Liked')
def __str__(self):
return self.headline
class Notifications(models.Model):
owner = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
property = models.ForeignKey(Property, null=True, blank=True,on_delete=models.CASCADE)
notification = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __str_(self):
return self.notification
HTML code
{% if accomodations %}
{% for accomodation in accomodations %}
<form action="{% url 'notification' %}" method="post">
{% csrf_token %}
<input type="hidden" name="owner_id" value="{{ accomodation.owner }}">
<button id="request-btn" name="property_id" value="{{ accomodation.id }}" class="btn btn-primary">Contact info:</button>
</form>
You need to pass the users instance. You can get user by this line of code
owner = User.objects.all().get(username=owner)
Note:
Every user should have differnt usernames
ValueError: Cannot assign "'hafis'": "Notifications.owner" must be a "User" instance. you're just passing in the ID but it requires it to be a User object.
def notification(request):
user = request.user
if request.method == 'POST':
property_id = request.POST['property_id']
owner = User.objects.get(id=request.POST['owner_id'])
property_object = Property.objects.get(id=property_id)
notification = user, "have intrested in your property"
property_object.notify.add(user)
notifications = Notifications.objects.create(notification=notification, owner=owner,
property=property_id)
notifications.save()
I have a view with a list of tasks and tried to do simple task allocation on click but it is not working. Could you please support? I see in my console sth like that:
"POST /task/allocate HTTP/1.1" 302 0.
Thank you.
L
model:
class Task(models.Model):
name = models.CharField(max_length=248)
note = models.TextField(blank=True, null=True)
priority = models.NullBooleanField(blank=True, null=True)
status = models.IntegerField(choices=TASK_STATUS, default=TASK_STATUS[0][0])
placed_date = models.DateField(auto_now=True)
due_date = models.DateTimeField(blank=True, null=True)
completed = models.BooleanField(default=False)
completed_date = models.DateField(blank=True, null=True)
created_by = models.ForeignKey(
User,
null=True,
blank=True,
related_name="hana_created_by",
on_delete=models.CASCADE)
assigned_to = models.ForeignKey(User,
null=True,
blank=True,
related_name="hana_assigned_to",
on_delete=models.CASCADE)
urls:
path('excel_table', ex_views.ExcelTableView.as_view(), name = "excel-table"),
path("task/add", ex_views.TaskAddView.as_view(), name="task-add"),
path("task/<int:task_id>/", ex_views.TaskDetailView.as_view(), name="task-detail"),
path("task/<int:pk>/edit", ex_views.TaskEditView.as_view(), name="task-update"),
path("task/allocate", views.task_allocator, name="task-allocate"),
views:
class TaskAllocateView(View):
def post(self, request):
if request.POST.get("task_allocate") is not None:
tasks = Task.objects.filter(assigned_to=None)
for task in tasks:
task.assigned_to = random.choice(User.objects.all())
task.status = 1
task.save()
current_site = get_current_site(request)
subject = render_to_string('email/assigned_subject.txt', {"task": task})
body = render_to_string('email/assigned_body.txt', {
'task': task,
'site': current_site,
})
to_email = task.assigned_to.email
email = EmailMessage(subject, body, to=[to_email])
email.send()
if tasks:
messages.success(request, "Tasks succesfully allocated to your employees. Check status!")
messages.success(request, ('Notification email has been sent to assignees!'))
else:
messages.warning(request, "All tasks already allocated!")
messages.warning(request, ('Notification email already sent!'))
return redirect(reverse("excel-table"))
return redirect(reverse("excel-table"))
template:
<form method="POST" action="{% url "task-allocate" %}" role="form" class="d-inline">
{% csrf_token %}
<div style="display:inline;">
<button class="btn btn-info btn-sm" type="submit" name="task_allocate">
Task Allocate
</button>
</div>
</form>
if t.assigned_to != None:
t.status = 1
t.save()
messages.success(request, "Tasks succesfully allocated to your employees. Check status!")
return redirect(reverse("excel-table"))
this if will never be executed because created_by will remain Non until you save it.
t.assigned_to = random.choice(User.objects.all())
if t.assigned_to != None:
you did this thinking that this t.assigned_to is not None anymore, well it remains None because you didnt save.
i hope this one will help you.
I have an app that let users create blogs and allow other users to comment on each other blogs.The Problem is .In order to create a comment object , I require the blog id and text . I can grab the text data via post but I'm having trouble getting the blog id from POST and the only way I can think of getting it is via value field in the form
How can I grab the value field from POST?
My models
class Blog(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
description = models.TextField()
class BlogComment(models.Model):
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User)
body = models.TextField()
blog = models.ForeignKey(Blog)
my forms.py
class BlogCommentForm(forms.ModelForm):
text = forms.CharField(required=False)
class Meta:
model = BlogComment
fields = ()
<form method ="POST"> {% csrf_token %}
<input type = "hidden" name="d" value= "blog.id" />
{{form}}
</form>
My views
def Blogs(request,blog_id):
form = BlogCommentForm(request.POST)
if request.method == "POST":
if form.is_valid():
text = form.cleaned_data['text']
value = form.cleaned_data['value']
form = BlogCommentForm()
blog.objects.get(pk=blog_id)
comment = BlogComment.objects.filter(blog=blog)
return render(request,'blogcomment.html',{'comment':comment,'form':form})
request.POST['d']
or to avoid raising an Exception if it's not there use
request.POST.get('d', False)
You can always get the blog id from ?= parameter in url.
When user goes to comment someone's blog the url might be http://yoursite.com/blog/id/comment or http://yoursite.com/blog/comment?blogid=12345.