First Commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Product
|
||||
|
||||
admin.site.register(Product)
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ProductsConfig(AppConfig):
|
||||
name = 'products'
|
||||
@@ -0,0 +1,30 @@
|
||||
# Generated by Django 2.2 on 2020-05-19 11:08
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Product',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=255)),
|
||||
('pub_date', models.DateTimeField()),
|
||||
('url', models.TextField()),
|
||||
('image', models.ImageField(upload_to='')),
|
||||
('icon', models.ImageField(upload_to='')),
|
||||
('votes_total', models.IntegerField()),
|
||||
('hunter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 2.2 on 2020-05-19 16:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('products', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='product',
|
||||
name='icon',
|
||||
field=models.ImageField(upload_to='images/'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='product',
|
||||
name='image',
|
||||
field=models.ImageField(upload_to='images/'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='product',
|
||||
name='votes_total',
|
||||
field=models.IntegerField(default=1),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2 on 2020-05-20 03:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('products', '0002_auto_20200519_2214'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='product',
|
||||
name='body',
|
||||
field=models.TextField(default=''),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2 on 2020-05-20 03:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('products', '0003_product_body'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='product',
|
||||
name='body',
|
||||
field=models.TextField(max_length=300),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
# Create your models here.
|
||||
class Product(models.Model):
|
||||
title= models.CharField(max_length=255)
|
||||
pub_date=models.DateTimeField()
|
||||
body=models.TextField(max_length=300)
|
||||
url=models.TextField()
|
||||
image=models.ImageField(upload_to='images/')
|
||||
icon=models.ImageField(upload_to='images/')
|
||||
votes_total=models.IntegerField(default=1)
|
||||
hunter=models.ForeignKey(User,on_delete=models.CASCADE)
|
||||
|
||||
def _str_(self):
|
||||
return self.title
|
||||
|
||||
def summary(self):
|
||||
return self.body[:100]
|
||||
|
||||
def pub_date_pretty(self):
|
||||
return self.pub_date.strftime('%b %e %Y')
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if error %}
|
||||
{{ error }}
|
||||
<br />
|
||||
<br />
|
||||
{% endif %}
|
||||
|
||||
<h1>Create</h1>
|
||||
|
||||
<form method="POST" action="{% url 'create' %}" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
Title:
|
||||
<br />
|
||||
<input type="text" name="title" />
|
||||
<br />
|
||||
Body:
|
||||
<br />
|
||||
<input type="text" name="body" />
|
||||
<br />
|
||||
URL:
|
||||
<br />
|
||||
<input type="text" name="url" />
|
||||
<br />
|
||||
Icon:
|
||||
<br />
|
||||
<input type="file" name="icon" />
|
||||
<br />
|
||||
Image:
|
||||
<br />
|
||||
<input type="file" name="image" />
|
||||
<br />
|
||||
<br />
|
||||
<input class="btn btn-primary" type="submit" value="Add Product" />
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,45 @@
|
||||
{% extends 'base.html'%}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<img src="{{ product.icon.url }}" class="img-fluid"/>
|
||||
</div>
|
||||
<div class="col-10">
|
||||
<a href="{{ product.url }}"><h1>{{product.title}}</h1></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<img src="{{ product.image.url }}" class="img-fluid"/>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<a href="javascript:{document.getElementById('upvote').submit()}"><button class="btn btn-primary btn-lg btn-block "><span class="oi oi-caret-top"></span>Upvote {{product.votes_total}}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-4 ">
|
||||
<h4>Hunted by {{ product.hunter.username }}</h4>
|
||||
</div>
|
||||
<div class="col-4 text-">
|
||||
<h4><span class="oi oi-clock"></span> {{ product.pub_date_pretty }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-8 ">
|
||||
<p>{{ product.body }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<form id="upvote" method="POST" action="{% url 'upvote' product.id %}" >
|
||||
{% csrf_token %}
|
||||
<input type="hidden">
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,32 @@
|
||||
{% extends 'base.html'%}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
{% for product in products.all %}
|
||||
|
||||
|
||||
|
||||
<div class="row pt-3">
|
||||
<div class="col-2" onclick="window.location='{% url 'detail' product.id %}';" style="cursor: pointer;">
|
||||
<img src="{{ product.icon.url }}" class="img-fluid"/>
|
||||
</div>
|
||||
<div class="col-6 onclick="window.location='{% url 'detail' product.id %}';" style="cursor: pointer;"">
|
||||
<h1>{{product.title}}</h1>
|
||||
<p>{{product.summary}}</p>
|
||||
</div>
|
||||
<div class="col-4 onclick="window.location='{% url 'detail' product.id %}';" style="cursor: pointer;"">
|
||||
<a href="javascript:{document.getElementById('upvote{{product.id}}').submit()}"><button class="btn btn-primary btn-lg btn-block "><span class="oi oi-caret-top"></span>Upvote {{product.votes_total}}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form id="upvote{{product.id}}" method="POST" action="{% url 'upvote' product.id %}" >
|
||||
{% csrf_token %}
|
||||
<input type="hidden">
|
||||
</form>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns=[
|
||||
path('create',views.create, name='create'),
|
||||
path('<int:product_id>/',views.detail, name='detail'),
|
||||
path('<int:product_id>/upvote',views.upvote, name='upvote'),
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
from django.shortcuts import render, redirect,get_object_or_404
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from .models import Product
|
||||
from django.utils import timezone
|
||||
|
||||
def home(request):
|
||||
products = Product.objects
|
||||
return render(request, 'home.html',{'products':products})
|
||||
|
||||
@login_required(login_url="/accounts/signup")
|
||||
def create(request):
|
||||
if request.method == 'POST':
|
||||
if request.POST['title'] and request.POST['body'] and request.POST['url'] and request.FILES['icon'] and request.FILES['image']:
|
||||
product = Product()
|
||||
product.title = request.POST['title']
|
||||
product.body = request.POST['body']
|
||||
if request.POST['url'].startswith('http://') or request.POST['url'].startswith('https://'):
|
||||
product.url = request.POST['url']
|
||||
else:
|
||||
product.url = 'http://' + request.POST['url']
|
||||
product.icon = request.FILES['icon']
|
||||
product.image = request.FILES['image']
|
||||
product.pub_date = timezone.datetime.now()
|
||||
product.hunter = request.user
|
||||
product.save()
|
||||
return redirect('/products/'+str(product.id))
|
||||
else:
|
||||
return render(request, 'create.html',{'error':'All fields are required.'})
|
||||
else:
|
||||
return render(request, 'create.html')
|
||||
|
||||
def detail(request,product_id):
|
||||
product= get_object_or_404(Product,pk=product_id)
|
||||
return render(request, 'detail.html',{'product':product})
|
||||
|
||||
@login_required(login_url="/accounts/signup")
|
||||
def upvote(request,product_id):
|
||||
if request.method=='POST':
|
||||
product= get_object_or_404(Product,pk=product_id)
|
||||
product.votes_total+=1
|
||||
product.save()
|
||||
return redirect('/products/'+str(product.id))
|
||||
Reference in New Issue
Block a user