Salut les gars! Bonjour, bonne soirée ou bonne nuit!
Salut, c'est moi. C'est Takurinton.
Cette fois, c'est comme créer une API avec Django et la frapper. En toile de fond, il y avait un problème que je ne pourrais pas mettre en œuvre sans faire quelque chose comme ça dans un certain sujet de notre université, donc j'ai l'impression que je vais le faire un peu. Eh bien, c'était assez difficile parce que j'étais dans un état d'ignorance. C'est une tâche gratuite, donc elle s'autodétruit complètement (; ∀ ;)
Le temps total requis était d'environ 6 heures, y compris le temps de recherche sur Google. S'il vous plaît par le guide.
Je l'ai fait en remodelant le site EC qui a été initialement réalisé par sous-traitance. Mais je ne devrais pas détruire le site en cours de mise à jour, j'ai donc pensé qu'il serait facile de créer un autre environnement dans Docker et de créer un environnement virtuel avec docker-compose. Je pense que seule la base de données changera que vous utilisiez Docker ou non, donc j'omettrai cette partie (j'écrirai bientôt les détails sur mon blog personnel)
OS | macOS Chatalina version 10.15.4 |
Langue | Python, Java |
Cadre | Django REST framework |
Cliquez ici pour un lien vers l'ensemble du framework Django REST (https://www.django-rest-framework.org/)
À l'origine, la base de données et la logique étaient solides, il n'y avait donc pas besoin de maintenance.
L'API créée cette fois acquiert les informations de commande. Comme image
Je veux obtenir le succès, alors je l'ai implémenté en conséquence.
La base de données liée à cela est la suivante.
models.py
class CustomUserManager(UserManager):
use_in_migrations = True
def _create_user(self, email, password=None, zip_code=None, address1=None, address2=None, address3=None, **extra_fields):
if not email:
raise ValueError('L'email est obligatoire et pas de couverture')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
phone_number_regex = RegexValidator(regex=r'^[0-9]+$', message = ("Tel Number must be entered in the format: '09012345678'. Up to 15 digits allowed."))
phone_number = models.CharField(validators=[phone_number_regex], max_length=15, verbose_name='numéro de téléphone')
zip_code = models.CharField(max_length=8)
address1 = models.CharField(max_length=40)
address2 = models.CharField(max_length=40)
address3 = models.CharField(max_length=40, blank=True)
user.save(using=self._db)
return email
def create_user(self, request_data, **kwargs):
if not request_data['email']:
raise ValueError('Users must have an email address.')
user = self.model(
email=request_data['email'],
first_name=request_data['first_name'],
last_name=request_data['last_name'],
# password=request_data['password'],
zip_code=request_data['zip_code'],
address1=request_data['address1'],
address2=request_data['address2'],
address3=request_data['address3'],
)
user.set_password(request_data['password'])
user.save(using=self._db)
return user
def create_superuser(self, email, phone_number=None, password=None, zip_code=None, address1=None, address2=None, address3=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
#username = models.CharField(_('username'), max_length=20, unique=True)
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30)
last_name = models.CharField(_('last name'), max_length=150)
zip_code = models.CharField(max_length=8)
address1 = models.CharField(max_length=40)
address2 = models.CharField(max_length=40)
address3 = models.CharField(max_length=40, blank=True)
phone_number_regex = RegexValidator(regex=r'^[0-9]+$', message = ("Tel Number must be entered in the format: '09012345678'. Up to 15 digits allowed."))
phone_number = models.CharField(validators=[phone_number_regex], max_length=15, verbose_name='numéro de téléphone', null=True, blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = CustomUserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def user_has_perm(self, user, perm, obj):
return _user_has_perm(user, perm, obj)
def has_perm(self, perm ,obj=None):
return _user_has_perm(self, perm, obj=obj)
def has_module_perms(self, app_label):
return self.is_staff
def get_short_name(self):
return self.first_name
class Meta:
# db_table = 'api_user'
swappable = 'AUTH_USER_MODEL'
class Company(models.Model):
name = models.CharField(max_length=255)
introduction = models.TextField(max_length=65536)
postal_code = models.CharField(max_length=8)
company_image = models.ImageField()
homepage = models.CharField(max_length=255, null=True, blank=True)
images = models.BooleanField(verbose_name='', default=False)
place = models.CharField(max_length=255)
def __str__(self):
return str(self.name)
class Product(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
contents = models.CharField(max_length=255)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
product_image = models.ImageField()
option = models.CharField(max_length=255, null=True, blank=True, default=None)
price = models.IntegerField()
def __str__(self):
return str(self.name)
class Cart(models.Model):
cart_id = models.IntegerField(null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
is_active = models.BooleanField(default=True)
pub_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return str(self.cart_id)
class UserInfomation(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, blank=True, null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
day = models.CharField(max_length=255, default=None)
time = models.CharField(null=True, blank=True, max_length=255, default=None)
status = models.BooleanField(default=False, null=True, blank=True)
total = models.IntegerField(null=True)
remark = models.TextField(max_length=65535, null=True, blank=True)
pub_date = models.DateTimeField(default=now)
def __str__(self):
return str(self.user)
class OrderItems(models.Model):
user = models.ForeignKey(UserInfomation, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, blank=True, null=True)
item = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True)
number = models.IntegerField(null=True)
price = models.IntegerField(null=True)
total = models.IntegerField(null=True)
Il y a d'autres tableaux, mais cette fois je les omettrai car je peux le faire avec juste ça.
Tout d'abord, si vous n'avez pas installé le framework rest, installez-le.
pip install djangorestframework
Ensuite, ajoutez les paramètres suivants à settings.py.
settings.py
...
INSTALLED_APPS = [
...
'rest_framework',
]
...
JWT_AUTH = {
'JWT_VERIFY_EXPIRATION': False, #Persistance des jetons
'JWT_AUTH_HEADER_PREFIX': 'JWT',
}
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
'NON_FIELD_ERRORS_KEY': 'detail',
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}
Ici, nous allons créer une fonction pour se connecter à un utilisateur existant. Cette fois, nous authentifierons toutes les demandes. Ceci est obligatoire car il permet uniquement aux utilisateurs connectés de fonctionner. Tout d'abord, créez un point de terminaison.
project_name/urls.py
from django.conf.urls import url
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
url(r'^login_/', obtain_jwt_token),
...,
]
L'ajout de ce point de terminaison termine la fonction de connexion. Il est indispensable que vous construisiez une base de données. get_jwt_token renverra un jeton d'authentification lorsque vous accédez à ce point de terminaison.
Je souhaite me connecter en tant qu'utilisateur existant. J'utiliserai ipython au stade expérimental (car c'est facile)
In [1]: import requests
In [2]: import json
In [3]: data = {'email': '[email protected]', 'password': 'hogehoge'}
In [4]: r = requests.post('localhost:8000/login_/', data=data)
In [5]: print(r.json())
Out[5]: {'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo5LCJ1c2VybmFtZSI6ImIxODA2NDI5QGdtYWlsLmNvbSIsImV4cCI6MTU5NDc5OTMwNCwiZW1haWwiOiJiMTgwNjQyOUBnbWFpbC5jb20ifQ.Torhy69ZyKMOOxQUUv3Ebn9V6wqSwUlsQUD5IPUaDJA'}
Un long JSON sera retourné comme ça. En guise de mise en garde pour le moment, Python a quelque chose comme json.dumps (dict) qui convertit le dictionnaire en JSON, mais si vous faites cela, vous obtiendrez une erreur. Seules les données de type dict sont transmises ici. Veuillez également conserver ce jeton retourné car vous l'utiliserez plus tard. Les données utilisées lors de la connexion sont l'adresse e-mail et le mot de passe qui sont les clés primaires. Si vous ne savez pas ce que c'est, lisez le code dans models.py.
En passant, dans les requêtes Python, vous pouvez mettre un corps dans les données et un en-tête dans les en-têtes. En utilisant r.json (), vous pouvez convertir la réponse en type dict et la convertir en un formulaire facile à utiliser. les requêtes et json sont assez denses. C'est dense. C'est dense.
Ensuite, je retournerai le JSON personnalisé pour moi-même. Personnellement, je suis tombé ici.
Premièrement, Serializer et Generic views J'ai pensé qu'il serait préférable de l'implémenter en utilisant / generic-views / #genericapiview), mais apparemment, il s'agit d'un JSON personnalisé (ceux-ci ne peuvent renvoyer que des champs qui existent dans une seule table). Je n'arrive pas à revenir, j'ai donc changé de méthode. Il m'a fallu beaucoup de temps pour arriver à la méthode actuelle, c'est donc ma réflexion.
Si vous souhaitez renvoyer un JSON personnalisé, vous n'avez pas besoin d'un sérialiseur, alors écrivez-le directement dans views.py. Le point de terminaison est décrit dans urls.py.
urls.py
from django.urls import path
from . import views
urlpatterns = [
...
path('get_shop_view', views.ShopView.as_view()), #Ajoute ça
]
views.py
from django.http import HttpResponse
from rest_framework import generics
class ShopView(generics.ListCreateAPIView):
# list(self, request, *args, **kwargs)Sera capable de générer du JSON personnalisé en utilisant
def list(self, request, *args, **kwargs):
#Liste des JSON à retourner enfin
return_list = list()
try:
user_info = UserInfomation.objects.all() #Obtenez tous les utilisateurs avec une expérience d'achat
for i in user_info:
order = OrderItems.objects.filter(user=i) #Spécifiez l'utilisateur
shop = order[0].item.company.name #Précisez la société
#Obtenir la liste des produits
order_items = dict()
for i in order:
order_items[i.item.name] = {
'price': i.item.price, #prix
'images': str(i.item.product_image) #URL de l'image
}
total = sum([i.total for i in order]) #montant total. Obtenez le total de la liste générée par l'inclusion de liste
date_time_ = UserInfomation.objects.get(cart=i.cart)
date_time = date_time_.day + date_time_.time #Obtenez le délai de livraison souhaité
#Mettez ces données dans la liste complète
return_list.append(
{
'user': str(i.user), #Courrier de l'utilisateur
'shop': shop, #Magasin où vous avez commandé
'order': order_items, #Liste des produits commandés
'total': total, #montant total
'datetime': date_time, #Délai de livraison souhaité
}
)
#Renvoie une liste vide si une erreur se produit
except:
pass
return Response(
return_list
)
Après avoir créé jusqu'à présent, j'enverrai une demande d'obtention au point de terminaison créé précédemment
In [1]: {'Content-Type': 'application/json',
'Authorization': 'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo5LCJ1c2VybmFtZSI6ImIxODA2NDI5QGdtYWlsLmNvbSIsImV4cCI6MTU5NDc5OTMwNCwiZW1haWwiOiJiMTgwNjQyOUBnbWFpbC5jb20ifQ.Torhy69ZyKMOOxQUUv3Ebn9V6wqSwUlsQUD5IPUaDJA'}
In[2]: order_list = requests.get('http://localhost:8000/get_shop_view', headers=headers)
In [3]: order_list.json()
Out[3]:
[{'user': '[email protected]',
'shop': 'Magasin B',
'order': {'Hamburger': {'price': 1000,
'images': 'IMG_4145_ykxb9h'}},
'total': 1000,
'datetime': '14 juillet 2020 Maintenant'},
{'user': '[email protected]',
'shop': 'Magasin B',
'order': {'Hamburger': {'price': 1000,
'images': 'IMG_4145_ykxb9h'},
'curry': {'price': 2,
'images': '11967451898714_y6tgch'}},
'total': 2002,
'datetime': '14 juillet 2020 Maintenant'},
{'user': '[email protected]',
'shop': 'Magasin B',
'order': {'Ragoût': {'price': 11111,
'images': 'IMG_4900_oyb5ny'},
'Hamburger': {'price': 1000,
'images': 'IMG_4145_ykxb9h'},
'café': {'price': 199,
'images': '54490_jawqyl'},
'curry': {'price': 2,
'images': '11967451898714_y6tgch'},
'crêpe': {'price': 100,
'images': 'tweet_p7chgi'},
'Takurinton': {'price': 100,
'images': 'npyl13'}},
'total': 24220,
'datetime': '16 juillet 2020 Maintenant'}]
C'est celui que j'avais mis dans le chariot à l'avance, mais il est revenu en toute sécurité! !! !! heureux ~! !! !! Jusqu'à présent, cela a pris environ 5 heures et 45 minutes. .. ..
Étant donné que le rapport est Java, je voulais pouvoir le consulter en Java, alors je l'ai recherché sur Google et c'était étonnamment facile. Je suis un peu heureux car je pensais que c'était une langue difficile. .. .. LOL
Test.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandler;
import java.nio.charset.StandardCharsets;
public class Test{
public static void main(String[] args){
try {
HttpRequest request = HttpRequest
.newBuilder(URI.create("http://localhost:8000/get_shop_view"))
.header("Content-Type", "application/json")
.header("Authorization", "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo5LCJ1c2VybmFtZSI6ImIxODA2NDI5QGdtYWlsLmNvbSIsImV4cCI6MTU5NDc5OTMwNCwiZW1haWwiOiJiMTgwNjQyOUBnbWFpbC5jb20ifQ.Torhy69ZyKMOOxQUUv3Ebn9V6wqSwUlsQUD5IPUaDJA")
.GET()
.build();
BodyHandler<String> bodyHandler = HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8);
HttpResponse<String> response = HttpClient.newBuilder().build().send(request, bodyHandler);
String body = response.body();
System.out.println(body);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Le code est encore long, mais acceptable. Cela semble être une position d'écriture dans HttpRequest. Vous pouvez utiliser le même jeton dans l'en-tête que vous avez obtenu précédemment. Je ne comprends pas vraiment, mais ...
Compilez et exécutez.
(base) Hogehoge:working takurinton$ javac Test.java
(base) Hogehoge:working takurinton$ java Test
[{'user': '[email protected]',
'shop': 'Magasin B',
'order': {'Hamburger': {'price': 1000,
'images': 'IMG_4145_ykxb9h'}},
'total': 1000,
'datetime': '14 juillet 2020 Maintenant'},
{'user': '[email protected]',
'shop': 'Magasin B',
'order': {'Hamburger': {'price': 1000,
'images': 'IMG_4145_ykxb9h'},
'curry': {'price': 2,
'images': '11967451898714_y6tgch'}},
'total': 2002,
'datetime': '14 juillet 2020 Maintenant'},
{'user': '[email protected]',
'shop': 'Magasin B',
'order': {'Ragoût': {'price': 11111,
'images': 'IMG_4900_oyb5ny'},
'Hamburger': {'price': 1000,
'images': 'IMG_4145_ykxb9h'},
'café': {'price': 199,
'images': '54490_jawqyl'},
'curry': {'price': 2,
'images': '11967451898714_y6tgch'},
'crêpe': {'price': 100,
'images': 'tweet_p7chgi'},
'Takurinton': {'price': 100,
'images': 'npyl13'}},
'total': 24220,
'datetime': '16 juillet 2020 Maintenant'}]
Je reviendrai en toute sécurité. React et Vue sont plus ennuyeux à cause du navigateur, mais Java est facile car il est complété sur la ligne de commande.
En fait, il y a beaucoup de choses telles que la création d'utilisateurs, l'acquisition d'informations utilisateur, l'acquisition d'informations sur le magasin, la liste des produits que le magasin a, etc. autres que ce que j'ai écrit ici. Comme il y a de nombreuses parties ici qui dépendent d'une table, il est plus rapide de créer en spécifiant des champs que personnalisés, il est donc important de les utiliser correctement. Je suis fatigué de toucher Java, alors je vais le laisser ici aujourd'hui. LOL
De plus, j'ai pu l'implémenter en environ 6 heures, mais cela semble être un long voyage car je dois encore jouer avec de plus en plus.
Il est difficile d'obtenir toutes les tâches de la classe en ligne avec le virus corona! Voulez-vous tester! Des collégiens qui y réfléchissent! Étudions ensemble autant que le virus corona et surmontons cette situation! Je ferai de mon mieux pendant encore 2 semaines! !!
Recommended Posts