#javascript #jquery #django #rest #serialization
#javascript #jquery #django #остальное #сериализация
Вопрос:
models.py
import uuid
import os
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager,
PermissionsMixin
from django.conf import settings
def recipe_image_file_path(instance, filename):
"""Generate file path for new recipe image"""
ext = filename.split('.')[-1]
filename = f'{uuid.uuid4()}.{ext}'
return os.path.join('uploads/recipe/', filename)
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
"""Creates and saves a new user"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(email=self.normalize_email(email), **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""Creates and saves a new super user"""
user = self.create_user(email, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""Custom user model that suppors using email instead of username"""
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
class Tag(models.Model):
"""Tag to be used for a recipe"""
name = models.CharField(max_length=255)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
def __str__(self):
return self.name
class Ingredient(models.Model):
"""Ingredient to be used in a recipe"""
name = models.CharField(max_length=255)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.name
class Recipe(models.Model):
"""Recipe object"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
title = models.CharField(max_length=255)
time_minutes = models.IntegerField()
price = models.DecimalField(max_digits=5, decimal_places=2)
link = models.CharField(max_length=255, blank=True)
ingredients = models.ManyToManyField('Ingredient')
tags = models.ManyToManyField('Tag')
image = models.ImageField(null=True, upload_to=recipe_image_file_path)
def __str__(self):
return self.title
serializers.py
from rest_framework import serializers
from django.contrib.auth import get_user_model
from core.models import Tag, Ingredient, Recipe
class TagSerializer(serializers.ModelSerializer):
"""Serializer for tag objects"""
class Meta:
model = Tag
fields = ('id', 'name')
read_only_fields = ('id',)
class IngredientSerializer(serializers.ModelSerializer):
"""Serializer for ingredient objects"""
class Meta:
model = Ingredient
fields = ('id', 'name')
read_only_fields = ('id',)
class RecipeSerializer(serializers.ModelSerializer):
"""Serialize a recipe"""
ingredients = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Ingredient.objects.all()
)
tags = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Tag.objects.all()
)
class Meta:
model = Recipe
fields = (
'id', 'title', 'ingredients', 'tags', 'time_minutes',
'price', 'link' # Add user here
)
read_only_fields = ('id',)
class RecipeDetailSerializer(RecipeSerializer):
"""Serialize a recipe detail"""
ingredients = IngredientSerializer(many=True, read_only=True)
tags = TagSerializer(many=True, read_only=True)
class RecipeImageSerializer(serializers.ModelSerializer):
"""Serializer for uploading images to recipes"""
class Meta:
model = Recipe
fields = ('id', 'image')
read_only_fields = ('id',)
create.html
{% extends 'base.html' %}
{% block content %}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Create a Recipe</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
// process the form
$('form').submit(function(event) {
var tags = $('select[name=tags]').val();
var tagsS = tags.toString();
var ingredients = $('select[name=ingredients]').val();
var ingredientsS = ingredients.toString();
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
var formData = {
'title' : $('input[name=T]').val(),
'tags' : tagsS,
'ingredients' : ingredientsS,
'time_minutes' : $('input[name=Time]').val(),
'price' : $('input[name=P]').val(),
'link' : $('input[name=link]').val(),
};
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : '/api/recipe/recipes/', // the url where we want to POST
data : formData, // our data object
dataType : 'json', // what type of data do we expect back from the server
encode : true
})
// using the done promise callback
.done(function(data) {
// log data to the console so we can see
console.log(data);
// here we will handle errors and validation messages
});
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
});
</script>
</head>
<body class="">
<br>
<div class="jumbotron">
<h1>Create a recipe</h1>
<br>
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label for="T">Title: </label>
<input class="form-control" type="text" name="T" value="">
</div>
<div class="form-group">
<label for="Ingr">Ingredients: </label>
<select class="form-control" multiple id="select-ingr" name="ingredients">
{% for ing in Ing %}
<option value="{{ing.pk}}">{{ing}}</option>
{%endfor%}
</select>
</div>
<div class="form-group">
<label for="Tag">Tags: </label>
<select class="form-control" multiple id="select-tags" name="tags">
{% for tag in Tag %}
<option value="{{tag.pk}}">{{tag}}</option>
{%endfor%}
</select>
</div>
<div class="form-group">
<label for="Time">Time: </label>
<input class="form-control" type="text" name="Time" value="">
</div>
<div class="form-group">
<label for="P">Price: </label>
<input class="form-control" type="text" name="P" value="">
</div>
<div class="form-group">
<label for="link">Link: </label>
<input class="form-control" type="text" name="link" value="">
</div>
<div class="form-group">
<input class="btn btn-success" type="submit" name="submit" value="Create">
</div>
</form>
</div>
</body>
</html>
{%endblock%}
Я использовал метод toString, потому что без него форма отправляет массив как null / 0
, поэтому, если я выбираю более одного массива в форме, я получаю ‘Неправильный тип. Ожидаемое значение pk, полученная строка.’
но если я выберу только одно, форма будет успешно отправлена Заранее Благодарю вас: D
о, да, я все еще новичок, поэтому, если вы сможете объяснить, я был бы благодарен