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/')
Related
I am using the YouTube Data API to create an object, but when I create a single object, it creates two objects - one with the proper details and one that is blank. How can I resolve this issue?
before creating object
after creating single object
I am trying with the following code.
view.py
class VideoCreateView(CreateView):
model = Video
form_class = VideoForm
template_name = "videos/video_form.html"
def form_valid(self, form):
video = Video()
video.url = form.cleaned_data['url']
parse = urllib.parse.urlparse(video.url)
video_id = urllib.parse.parse_qs(parse.query).get('v')
if video_id:
video.youtube_id =video_id[0]
response = requests.get(f'https://youtube.googleapis.com/youtube/v3/videos?part=snippet&id={video_id[0]}&key={YOUTUBE_API_KEY}')
json = response.json()
items = json["items"]
assert len(items) <= 1
if len(items):
title = items[0]["snippet"]["title"]
video.title = title
video.save()
else:
title = "N/A"
return super().form_valid(form)
models.py
class Video(models.Model):
title = models.CharField(max_length=255)
url = models.URLField()
youtube_id = models.CharField(max_length=255)
slug = models.SlugField(blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("videos:video_detail", kwargs={"slug":self.slug})
def video_pre_save_reciever(sender,instance,*args, **kwargs):
if not instance.slug:
instance.slug = unique_slug_generator(instance)
pre_save.connect(video_pre_save_reciever,Video)
if more code is require than tell me in comment , i will update my question with that information.
The view VideoCreateView inherits CreateView. CreateView inherits ModelFormMixin which defines form_valid method.
def form_valid(self, form):
"""If the form is valid, save the associated model."""
self.object = form.save()
return super().form_valid(form)
You save the video object and call the super form_valid which saves the form(in turn creating a model object) again. Hence, causing a double creation. I suggest modifying the form and passing it to super instead of manually saving it.
Another option is to inherit the View with django.views.generic.View. This would avoid form save.
I suggest you follow the first approach.
I have solve this my problem by removing all the form_valid code from the views and add that inside the model
class Video(models.Model):
title = models.CharField(max_length=255)
url = models.URLField()
youtube_id = models.CharField(max_length=255)
slug = models.SlugField(blank=True)
def save(self,*args,**kwargs):
parse = urllib.parse.urlparse(self.url)
video_id = urllib.parse.parse_qs(parse.query).get('v')
if video_id:
self.youtube_id =video_id[0]
response = requests.get(f'https://youtube.googleapis.com/youtube/v3/videos?part=snippet&id={video_id[0]}&key={YOUTUBE_API_KEY}')
json = response.json()
title = json["items"][0]["snippet"]["title"]
self.title = title
super(Video,self).save(*args,**kwargs)
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.
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
I wrote a login page, of course it contains a form. Then I wrote my LoginView use class like this:
class LoginView(View):
def get(self, request):
return render(request, "login.html")
def post(self, request):
login_form = LoginForm(request.POST)
if login_form.is_valid():
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return render(request, 'index.html')
else:
return render(request, 'login.html', {'msg':'账号未激活!'}, {'login_form':login_form})
else:
return render(request, 'login.html', {'msg':'用户名不存在!'}, {'login_form':login_form})
else:
return render(request, 'login.html', {'msg':'用户名或密码错误!'}, {'login_form':login_form})
Ignore the Chinese you may not know.
I tried to input wrong username and password, it should return the same page with error message to allow me to input again, but...
It return a page contains all html code, seems like the browser didn't compile the codes?
If there's a mistake I made in LoginView?
You need to access the form.cleaned_data not request.POST,
username = login_form.cleaned_data['username']
password = login_form.cleaned_data['password']
I have a text area in a django based website that displays the content of a database field.
I'd like to be able to edit this field and submit it to a function which updates the field in the database.
I know how I can call a function in a views.py which then send back the result of the query using render_to_response to a new webpage.
So in summary, how do I adress a function in a django/python script using a html form without the need to refer to another url?
It's usually recommended to use Post/Redirect/Get pattern, for example:
def myview(request, **kwargs):
if request.POST:
# validate the post data
if valid:
# save and redirect to another url
return HttpResponseRedirect(...)
else:
# render the view with partial data/error message
if request.GET:
# render the view
return render_to_response(...)
Use AJAX:
1) Create a view to handle form submission:
def my_ajax_form_submission_view(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
# save data or whatever other action you want to take
resp = {'success': True}
else:
resp = {'success': False}
return HttpResponse(simplejson.dumps(resp), mimetype='application/json')
else:
return HttpResponseBadRequest()
Then, tie the view into your urlpatterns
2) Submit form via AJAX (uses jQuery):
$('#my-form-id').submit(function(){
var $form = $(this);
$.post('/url/to/ajax/view/', $form.serialize(), function(data, jqXHR){
if (data.success) {
alert('Form submitted!');
} else {
alert('Form not valid');
}
});
return false;
});
That's the basics. You can and should provide more detailed return responses, error handling, form validation/checking, etc.
This is the standard views code pattern that I've been using.
def payment_details(request, obj_id):
yourobj = get_object_or_404(Obj, pk=obj_id)
form = TheForm(instance=yourobj)
if request.method == 'POST':
form = TheForm(request.POST, instance=yourobj)
if form.is_valid():
yourobj = form.save()
messages.success(request, 'Yourobj is saved!')
url = reverse('SOMEURL')
return redirect(url)
template = 'SOMETEMPLATE'
template_vars = {'TEMPLATEVARS': TEMPLATEVARS}
return render(request, template, template_vars)
Having watched the Advanced Forms talk at DjangoCon, one could re-write the above view like this:
def payment_details(request, obj_id):
yourobj = get_object_or_404(Obj, pk=obj_id)
form = TheForm(request.POST or NONE, instance=yourobj)
if request.method == 'POST' and form.is_valid():
yourobj = form.save()
messages.success(request, 'Yourobj is saved!')
url = reverse('SOMEURL')
return redirect(url)
template = 'SOMETEMPLATE'
template_vars = {'TEMPLATEVARS': TEMPLATEVARS}
return render(request, template, template_vars)