I want to POST a message to the Message table in my db, which contains the following fields:
id;
body;
normaluser;
chat.html:
<form method="post" id="msg">
<div class="form-group">
<label for="comment">Message:</label>
<textarea class="form-control" rows="5" id="comment"></textarea>
</div>
{% csrf_token %} {{ form.as_p }}
<button type="submit">Enter</button>
</form>
views.py
#login_required
def msg(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
body = form.cleaned_data.get('body')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
Message(request, user)
else:
form = 'msg'
args = {'form': form}
return render(request, 'accounts/chat.html', args)
class MessageListView(APIView):
def get(self, request): # lista objectos
serializer = MessageSerializer(instance=Message.objects.all(), many=True)
return Response(serializer.data)
def post(self, request): # cria objecto
serializer = MessageSerializer(data=request.data, many=False)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
models.py
class Message(models.Model):
body = models.CharField(max_length=500)
normaluser = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.body
serializer.py
class MessageSerializer(serializers.ModelSerializer):
normaluser = MessageUserSerializer(many=False, read_only=True)
class Meta:
model = Message
fields = ('id', 'body', 'normaluser')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
I am basing my view from the def I use to make a new user. But I'm not understanding how to change it to accept a message, which also receives the info of the user authenticated at the time he sends the message. I am using the django User table to create users and login.
The Django user creation form is for creating a user. You basically want to customise this to add an extra message field and save this as a related object. Your form should be something like this (not had a chance to test it):
class UserCreateWithMessageForm(UserCreationForm):
message = forms.TextField()
def save(self, #args, **kwargs):
user = super(UserCreateWithMessageForm, self).save()
message_txt = self.cleaned_data['message']
Message.objects.create(body=message_txt, normaluser=user)
return user
Related
I have a page that details a post and comments on that post. The pk for this page is the post pk. I want to be able to construct comments using symbols only. I have a series of symbols saved to the database that are all associated with a category class. I have a form on my page that can select one of those categories, but how do I get an AJAX call to load all the symbols in that category? The user will need to be able to chop and change between categories so I wanted to do this with AJAX rather than reload the page each time. So far, all I get are 404, not founds. I want to do this so that I can drag or select symbols to add to comments. I've tried lots of different formats to get the URLs to work (both in urls.py and in main.js) so I can't list off all the alternatives that I've tried as it's all a bit overwhelming. I've also read through a heap of questions on here and other sites but nothing seems to match what I am trying to do. Any help would be appreciated.
Symbols are saved in media/uploads/symbol_files/
Symbols have a many-to-many relationship with comments through the model. All this is working fine so I haven't included it below.
At the moment the template is set up to populate a second form with the symbols from the selected category, I'll change this later, I've just got it like this for convenience.
Here's an example of output from the terminal:
Not Found: /posts/1/get_symbols/Alphabet
Where "Alphabet" is the name of one of the categories.
models.py:
class SymbolCategory(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
def get_symbols(self):
return self.symbol_set.all()
class Meta:
verbose_name = "SymbolCategory"
verbose_name_plural = "SymbolCategories"
class Symbol(models.Model):
name = models.CharField(max_length=50)
image = models.FileField(upload_to='uploads/symbol_files')
category = models.ForeignKey(SymbolCategory, on_delete=models.CASCADE)
def __str__(self):
return f'{self.name}-{self.pk}'
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length = 100)
body = models.TextField(max_length = 500)
video_file = models.FileField(blank=True, upload_to='uploads/video_files', validators = [FileExtensionValidator(allowed_extensions=['mp4', 'webm'])])
thumbnail = models.FileField(blank=True, upload_to='uploads/thumbnails', validators = [FileExtensionValidator(allowed_extensions=['png', 'jpg','jpeg'])])
date_posted = models.DateTimeField(default=timezone.now)
category = models.ForeignKey(PostCategory,blank=True, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "Posts"
views.py:
class DetailPost(View):
def get(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
symbol_comments = SymbolComment.objects.filter(post=post).order_by('-created_on')
categories = SymbolCategory.objects.all()
form_comment = CommentForm()
symbol_get_form = SymbolGetForm()
context = {
'object': post,
'form_comment': form_comment,
'symbol_comments': symbol_comments,
'symbol_get_form': symbol_get_form,
'categories': categories,
}
return render(request, 'posts/detail_post.html', context)
def post(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
form_comment = CommentForm(request.POST)
if form_comment.is_valid():
symbol_comments = SymbolComment(
user = self.request.user,
post = post
)
symbol_comments.save()
symbol_comments = SymbolComment.objects.filter(post=post).order_by('-created_on')
context = {
'object': post,
'form_comment': form_comment,
'symbol_comments': symbol_comments,
}
return render(request, 'posts/detail_post.html', context)
def get_symbols(request):
if request.is_ajax():
if request.method == "POST": # I've tried with GET but it doesn't work either, at the moment it currently has POST but I think this is wrong.
category_name = request.POST['category_name']
print(category_name)
try:
category = SymbolCategory.objects.filter(id = category_name).first()
symbols = Symbol.objects.filter(category = category)
except Exception:
data['error_message'] = 'error'
return JsonResponse(data)
return JsonResponse(list(symbols.values('name', 'image_field')), safe = False)
urls.py:
urlpatterns = [
path('<int:pk>/', DetailPost.as_view(), name='detail-post'),
path('get_symbols/', get_symbols, name='get-symbols'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
template:
{% csrf_token %}
<div class="col-md-6">
<div class="form-group">
<label for="inputStatus">Category</label>
<select id="select-category" class="form-control-sm custom-select">
<option selected disabled>Choose a symbol category</option>
{% for category in categories %}
<option value="{{category.name}}">{{category.name}}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="inputStatus">Symbol</label>
<select id="category-symbol" class="form-control-sm custom-select" name="symbol">
<option selected disabled>Choose a symbol</option>
</select>
</div>
</div>
main.js:
$("#select-category").change(function () {
const categoryName = $(this).val();
$.ajax({
type: "POST",
url: `get_symbols/${categoryName}`,
data: {
'category_name': categoryName,
'csrfmiddlewaretoken':$('input[name=csrfmiddlewaretoken]').val(),
},
success: function (data) {
let html_data = '<option value="">---------</option>';
data.forEach(function (data) {
html_data += `<option value="${data.id}">${data.name}</option>`
});
console.log(data)
$("#category-symbol").html(html_data);
}
});
});
The url needed to be
'<int:pk>/'get_symbols'/<int:id>/'
There were a few other bugs that needed fixing too.
I have two models and two different forms. Tow forms are combined in a single view function. The two forms are combined in a single HTML form. Everything is working fine when I submit the HTML form except the images are not saved.
Here are the tow models:
class Posts(models.Model):
user = models.ForeignKey(MyUser, on_delete=models.CASCADE)
post_category = models.ForeignKey(Post_Category,
on_delete=models.CASCADE)
post_title = models.CharField(max_length=256)
post_detail = models.TextField(max_length=65536)
def __str__(self):
return "%s %s %s %s " % (
self.user, self.post_category, self.post_title,
self.post_detail)
class Meta:
verbose_name_plural = "Posts"
class Images(models.Model):
post = models.ForeignKey(Posts, on_delete=models.CASCADE)
images = models.ImageField(upload_to='images', blank=True, null=True )
def __str__(self):
return "%s %s" % (self.post, self.images)
class Meta:
verbose_name_plural = "images"
the forms are:
class PostsForm(forms.ModelForm):
class Meta:
model = Posts
fields = [
'post_category',
'post_title', 'post_detail',
]
class ImagesForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
kwargs.setdefault('label_suffix', '')
super(ImagesForm , self).__init__(*args, **kwargs)
self.fields['car_images'].widget.attrs.update({'class' : 'image',
'style':'display:none','id':'input-image-hidden',
'onchange':"document.getElementById('image-preview').src = window.URL.createObjectURL(this.files[0])" ,
'type':'file', "name":"images", 'accept':'image/*'})
class Meta:
model = Images
fields = [
'images',
]
widgets = {
'images': forms.ClearableFileInput(attrs={'multiple': True}),
}
Here is the view function:
from django.forms import inlineformset_factory
from django.utils.translation import ugettext_lazy as _
def post(request):
form = PostsForm()
imagesForm = ImagesForm()
template_name = 'path/to/template.html'
success_url = 'user_profile.html'
form = PostsForm(request.POST or None)
imagesForm = ImagesForm(request.POST or None,
request.FILES or None)
if form.is_valid() and imagesForm.is_valid():
new_post = form.save(commit=False)
new_post.user = request.user
new_post = form.save()
imagesForm.save(commit=False)
for file in request.FILES.getlist('images'):
instance = Images(
post= Posts.objects.get("images"),
images=file
)
instance.save()
return redirect('index')
else:
imagesForm = ImagesForm(request.POST or None, request.FILES or
None)
return render(request, template_name, {'imagesForm': imagesForm,
'form': form})
When the HTML form is submitted, all data are saved except the images( no error pups up).the HTML form is displayed again rather than redirect to the user profile page.
Can you please advise me to what is going on and where is the possible error or errors. Can you help me to save multiple images
NOTE: USING inline formset factory is not possible if I have to set extra parameter. I do not want to limit user to upload limited numbers of images.
How can i use my custom form called PayForm inside a template (Post.html) which is the template of a view called Post I tried to point both of the views to the same template but as i was told you can't point two views to the same template so i am currently stuck on this
models.py
from django.db import models
from django.urls import reverse
from PIL import Image
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
created = models.DateTimeField(auto_now_add=True)
content = models.TextField(default="---")
current_price = models.IntegerField(default=0)
reduction = models.IntegerField(default=0)
original_price = models.IntegerField(default=0)
Status = models.CharField(max_length=5, default="✓")
img = models.CharField(max_length=255)
sold = models.IntegerField(default=0)
endday = models.CharField(max_length=30, default="apr 27, 2018 16:09:00")
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.title
def get_absolute_url(self):
return reverse('Products.views.post', args=[self.slug])
def __str__(self):
return self.title
class Payment(models.Model):
Author = models.CharField(max_length=255)
Product = models.CharField(max_length=255)
Payment_ID = models.CharField(max_length=255)
Status = models.CharField(max_length=5, default="X")
Review_result = models.CharField(max_length=255, default="Not yet reviewed")
Address = models.CharField(max_length=255, default='')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.Status
def __str__(self):
return self.Status
views.py
from django.shortcuts import render, render_to_response , get_object_or_404, redirect
from .models import Post
from django.contrib.auth import authenticate, login, logout
from .forms import RegistrationForm, PayForm
def index(request):
posts=Post.objects.all()
return render(request, 'Index.html', {"posts": posts})
def post(request, slug):
return render(request, 'post.html', {'post': get_object_or_404(Post, slug=slug)})
def new_payment(request):
template ='payment.html'
if request.method == 'POST':
form = PayForm(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
print('form invalid')
else:
form = PayForm({'Author':request.user.username})
context = {
'form' : form,
}
return render(request, template, context)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Payment, Post
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
class PayForm(forms.ModelForm):
class Meta:
model = Payment
fields = ['Author', 'Product', 'Payment_ID', 'Address']
If someone can help me with this it would be greatly appreciated
If you have already created new_payment_form.html(or whatever you have called it) you can simply add to the post.html by using the {% include %} tag surrounded with appropriate <form> tags and whatever you need to go with it. The {% include %} essentially copies and pastes all the code from whatever file you have inside the tag. And a general rule, Product means class and product means variable or field.
# new_payment_form.html is the name of your html file.
# template_path is the directory to your template.
<form>
{% include 'template_path/new_payment_form.html' %}
<button> # submit button
</form>
However, you still need to process it in the view.
def post(request, slug):
"""
(all the if: else: stuff)
"""
# Set new_payment product
new_payment = PayForm(initial={'Product': slug})
return render(request, 'post.html', {'post': get_object_or_404(Post, slug=slug), 'new_payment': new_payment})
You will probably rewrite your view, and there are some details to figure out, but that should get you headed in the right direction. You might want to change slug to a product id or pk.
This is an excerpt of my view.py
def routineInput(request):
if request.method == 'POST':
today = datetime.now
form = CreateRoutine(request.POST)
if form.is_valid():
return HttpResponseRedirect('/todo/saved/')
else:
form = CreateRoutine()
return render(request, 'todo/croutine.html', {'form': form})
So the idea is that I have a simple input form where I put a name into it and it should push this name into a table in my database. My code is coming thorough and it shows my /todo/saved page but my POST request doesn't seem to get sent to my table or my table is rejecting it or something.
My model.py class:
class Todolist(models.Model):
name = models.TextField()
created_at = models.DateTimeField(default = datetime.now, blank = True)
updated_at = models.DateTimeField(default = datetime.now, blank = True)
You are not saving your form data.
do
if form.is_valid():
form.save()
return HttpResponseRedirect('/todo/saved/')
I created a view to create a new object. In the DRF default page everything works fine, but when I try to create an simple HTML page as a user interface (by adding renderer_classes and template_name to the view), the following error occurs: 405 Method Not Allowed.
I created an html page to retrieve/update a client detail information, and it works fine. However, I was unable to do so to create a new client.
models.py
class Client(models.Model):
client_rut = models.CharField(max_length=12, unique=True, verbose_name="RUT")
client_name = models.CharField(max_length=250, verbose_name="Nombre Cliente")
client_region = models.CharField(max_length=50, verbose_name="Region")
client_tel = models.CharField(max_length=20, blank=True, verbose_name="Telefono")
client_email = models.EmailField(blank=True, verbose_name="E-mail")
is_active = models.BooleanField(default=True, verbose_name="Activo")
class Meta:
ordering = ['client_rut']
def __str__(self):
return self.client_rut + ' - ' + self.client_name
urls.py
urlpatterns = [
# /clients/
url(r'^$', views.ClientView.as_view(), name='clients'),
url(r'^(?P<pk>[0-9]+)/$', views.ClientDetailView.as_view(), name='clientdetail'),
url(r'^create/$', views.ClientCreateView.as_view(), name='clientcreate')
]
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html', 'xml'])
serializers.py
class ClientListSerializer(ModelSerializer):
url = HyperlinkedIdentityField(view_name='clients:clientdetail',)
class Meta:
model = Client
fields = '__all__'
class ClientDetailSerializer(ModelSerializer):
class Meta:
model = Client
fields = '__all__'
views.py
#this view works fine
class ClientDetailView(views.APIView):
queryset = Client.objects.all()
serializer_class = ClientDetailSerializer
renderer_classes = [TemplateHTMLRenderer]
template_name = 'clientdetail.html'
def get(self, request, pk):
client = get_object_or_404(Client, pk=pk)
serializer = ClientDetailSerializer(client)
return Response({'serializer': serializer, 'client': client})
def post(self, request, pk):
client = get_object_or_404(Client, pk=pk)
serializer = ClientListSerializer(client, data=request.data)
if not serializer.is_valid():
return Response({'serializer': serializer, 'client': client})
serializer.save()
return redirect('clients:clients')
# this one does not
class ClientCreateView(generics.ListCreateAPIView):
queryset = Client.objects.all()
serializer_class = ClientListSerializer
renderer_classes = [TemplateHTMLRenderer]
template_name = 'clientcreate.html'
def post(self, request):
Client.objects.create()
return redirect('clients:clients')
clientcreate.html
{% load rest_framework %}
<html><body>
<form action="{% url 'clients:clientcreate' %}" method="POST">
{% csrf_token %}
<div class="col-xs-6 ">
{% render_form serializer %}
</div>
<div>
<input type="submit" value="Grabar">
</div>
</form>
</body></html>
clientdetail.html is almost identical to clientcreate.html, save for this:
<form action="{% url 'clients:clientdetail' pk=client.pk %}" method="POST">
I think I've seen all 405 related questions and I just couldn't solve my problem (doesn't necessarily mean the answer's not out there though).
Hope someone can help me with this one.
Thanks!