Para agregar estilos, se integró Tailwind CSS usando un CDN. Se colocó el código del CDN en base.html y se añadió un ejemplo para verificar su funcionamiento. Se utilizan clases de Tailwind para mejorar la apariencia y organización de los elementos en el HTML.
¿Cómo optimizamos la interfaz con Hyper UI?
Hyper UI facilita el uso de HTML preparado para Tailwind CSS. Se copió y pegó código HTML de Hyper UI en el template de la lista de productos, adaptando nombres y precios de productos, y validando la existencia de imágenes antes de mostrarlas. Se comentó el botón de "agregar al carrito" usando tags de comentarios de Django Templates para futuras funcionalidades.
Si ocupaste ayuda de como mostrar la lista de productos, recuerda que en el archivo view donde creamos el ProductListView al profe le falto enseñar la importación:
from products.modelsimportProduct
aunque es fácil de saber que hace falta una importación aquí se las dejo por si lo necesitan 👍
Gracias, esa me faltaba para que corra el programa
A mi no me funcionaba con ese, pero si me funcipnó el siguiente:
from .<u>models</u> import <u>Product</u>
list_product.html
<h2>Lista de productos</h2><ul> {% for product in products %}
<li> {{product.name}}
<p>{{product.price}}</p> {% if product.photo %}
<imgsrc="{{product.photo.url}}"alt="{{product.name}}"style="max-height:100px;"> {% endif %}
</li> {% endfor %}
</ul>```\<h2>Lista de productos\</h2>\<ul> {% for product in products %}
  \<li> {{product.name}} \<p>{{product.price}}\</p> {% if product.photo %} \<imgsrc="{{product.photo.url}}"alt="{{product.name}}"style="max-height:100px;"> {% endif %} \</li> {% endfor %}\</ul>
Hola Si, asi esta quedano mi Coffee Shop con los Estilos de TailWindCSS .
\nYo estoy usando urls de la web en lugar de imagenes locales, asi es mucho mas facil, cuando este desplegado en AWS le cambiare eso con un local storage en un bucket de S3 en la nube para almacenar imagnees reales de coffee drinks.
from django importformsfrom.modelsimportProduct# ProductsFormsclassProductForm( forms.Form): name = forms.CharField(max_length=64, label="Product_Name") description = forms.CharField(widget=forms.Textarea, max_length=255, label="Product_Description") price = forms.DecimalField(max_digits=8, decimal_places=2, label="Product_Price") stock = forms.IntegerField(label="Stock") available = forms.BooleanField(required=False, initial=True, label="Available") product_image = forms.URLField(max_length=200, required=False, label="Product_Image") category = forms.CharField(max_length=32, label="Product_Category") def clean_price(self): price = self.cleaned_data.get('price')if price is not None and price <0: raise forms.ValidationError("Price cannot be negative.")return price
def save(self): product =Product.objects.create( name=self.cleaned_data['name'], description=self.cleaned_data['description'], price=self.cleaned_data['price'], stock=self.cleaned_data['stock'], available=self.cleaned_data['available'], product_image=self.cleaned_data.get('product_image',''), category=self.cleaned_data['category'],)return product
solo cambia esto:
success_url = reverse_lazy('add_products') por
success_url = reverse_lazy('list_products') y listo campeón
Hablando de TailwindCss, también les recomiendo buscar componentes desde Flowbite:
Y aqui pueden ver card que puede usar:
Ya lo he usando antes y me gusta mucho, si uno trabaja mucho con tailwind deberia considera la version completa con todos sus componentes.
El mundo del frontend tiene muchas alternativas, qué bueno que estén pudiendo usar otras junto con Django!
Para añadir al directorio de templates también se puede usar de la siguiente forma, sin necesidad de hacer uso del os.path.join, como también lo explica el comentario que se mostró en el video
'DIRS': [ BASE_DIR / 'templates' ],
Gracias. Más sencillo de esta forma.
Si nadie se preguntó cómo colocar si está disponible o no un producto, lo hacen con esto:
{{ product.avaliable|yesno:"Sí,No"}}
Alguien me puede explicar que extensión debo instalar para usar el HTML como le sale al profesor?
Debes instalar la extensión Tailwind CSS utilizando el método CDN llamado Play CDN como se explicó en la clase. Esto permite agregar estilos reutilizables a través de Tailwind en el archivo base HTML.
Con Emmet
tengo la version 6 de Django y no es necesario usa el os basta con solo poner el nombre del directorio asi , creo que en versiones anteriores a la 4 se usa el OS
Se me hizo algo complicado agregar fotos, pero ahi vamos. Hyperui es muuy util
Las imagenes en django suelen ser complicadas.
Te recomiendo que busques como funciona media y static.
Con eso puedes entender mejor!
Es poco pero es trabajo honesto 👌👌
Muy buen progreso
Ahora mismo para las versiones más recientes ya no se usa "os.path.join" para la construcción de rutas, esta forma ha sido remplazada por el uso del módulo "pathlib" que es una biblioteca más moderna y orientada a objetos de python.
Con pathlib, la unión de rutas se realiza de forma natural utilizando el operador de barra (/), lo que hace que el código sea más fácil de leer y escribir. Por ejemplo, en lugar de os.path.join(BASE_DIR, 'templates'), ahora se utiliza la expresión más concisa BASE_DIR / 'templates'.
from django.views.generic.base import TemplateView
classProductListView(TemplateView): template_name ='products/list_product.html'defget_context_data(self): products = Product.objects.all() context ={'products': products
}return context
```y usar ListView
```js
from django.views import genericfrom django.views import generic
classProductViewList(generic.ListView): model = Product
template_name ='products/list_product.html' context_object_name ='products'```cual es mas común o mejor practica?
Quizas en los casos donde no exista ya una vista o template de vista y tengas que hacerlo desde 0. Existe FormView, ListView... en el momento en que no vayas a usar uno de esos existentes, posiblemente convendria usar un TemplateView.
Cuando vayamos a responder peticiones GET y renderizar una plantilla HTML. Es decir, cuando no tengamos que procesar formularios ni lógica especial.
Aunque sí se podría enviar información mediante
def get_context_data(self, **kwargs)
y enviar, por ejemplo, un mensaje de bienvenida