-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #219 from pennlabs/rookie-subletting
Create Subletting
- Loading branch information
Showing
18 changed files
with
1,574 additions
and
373 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from django.contrib import admin | ||
from django.utils.html import mark_safe | ||
|
||
from sublet.models import Amenity, Offer, Sublet, SubletImage | ||
|
||
|
||
class SubletAdmin(admin.ModelAdmin): | ||
def image_tag(self, instance): | ||
images = ['<img src="%s" height="150" />' for image in instance.images.all()] | ||
return mark_safe("<br>".join(images)) | ||
|
||
image_tag.short_description = "Sublet Images" | ||
readonly_fields = ("image_tag",) | ||
|
||
|
||
admin.site.register(Offer) | ||
admin.site.register(Amenity) | ||
admin.site.register(Sublet, SubletAdmin) | ||
admin.site.register(SubletImage) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class SublettingConfig(AppConfig): | ||
name = "sublet" | ||
verbose_name = "Subletting" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# Generated by Django 3.2.23 on 2023-11-12 20:33 | ||
|
||
import django.db.models.deletion | ||
import phonenumber_field.modelfields | ||
from django.conf import settings | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="Amenity", | ||
fields=[("name", models.CharField(max_length=255, primary_key=True, serialize=False)),], | ||
), | ||
migrations.CreateModel( | ||
name="Offer", | ||
fields=[ | ||
( | ||
"id", | ||
models.AutoField( | ||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||
), | ||
), | ||
("email", models.EmailField(blank=True, max_length=255, null=True)), | ||
( | ||
"phone_number", | ||
phonenumber_field.modelfields.PhoneNumberField( | ||
blank=True, max_length=128, null=True, region=None | ||
), | ||
), | ||
("message", models.CharField(blank=True, max_length=255)), | ||
("created_date", models.DateTimeField(auto_now_add=True)), | ||
], | ||
), | ||
migrations.CreateModel( | ||
name="Sublet", | ||
fields=[ | ||
( | ||
"id", | ||
models.AutoField( | ||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||
), | ||
), | ||
("title", models.CharField(max_length=255)), | ||
("address", models.CharField(blank=True, max_length=255, null=True)), | ||
("beds", models.IntegerField(blank=True, null=True)), | ||
("baths", models.IntegerField(blank=True, null=True)), | ||
("description", models.TextField(blank=True, null=True)), | ||
("external_link", models.URLField(max_length=255)), | ||
("min_price", models.IntegerField()), | ||
("max_price", models.IntegerField()), | ||
("created_at", models.DateTimeField(auto_now_add=True)), | ||
("expires_at", models.DateTimeField()), | ||
("start_date", models.DateField()), | ||
("end_date", models.DateField()), | ||
("amenities", models.ManyToManyField(blank=True, to="sublet.Amenity")), | ||
( | ||
"favorites", | ||
models.ManyToManyField( | ||
blank=True, related_name="sublets_favorited", to=settings.AUTH_USER_MODEL | ||
), | ||
), | ||
( | ||
"sublettees", | ||
models.ManyToManyField( | ||
blank=True, | ||
related_name="sublets_offered", | ||
through="sublet.Offer", | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
( | ||
"subletter", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL | ||
), | ||
), | ||
], | ||
), | ||
migrations.CreateModel( | ||
name="SubletImage", | ||
fields=[ | ||
( | ||
"id", | ||
models.AutoField( | ||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||
), | ||
), | ||
("image", models.ImageField(upload_to="sublet/images")), | ||
( | ||
"sublet", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
related_name="images", | ||
to="sublet.sublet", | ||
), | ||
), | ||
], | ||
), | ||
migrations.AddField( | ||
model_name="offer", | ||
name="sublet", | ||
field=models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
related_name="offers", | ||
to="sublet.sublet", | ||
), | ||
), | ||
migrations.AddField( | ||
model_name="offer", | ||
name="user", | ||
field=models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
related_name="offers_made", | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
migrations.AddConstraint( | ||
model_name="offer", | ||
constraint=models.UniqueConstraint(fields=("user", "sublet"), name="unique_offer"), | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from django.contrib.auth import get_user_model | ||
from django.db import models | ||
from phonenumber_field.modelfields import PhoneNumberField | ||
|
||
|
||
User = get_user_model() | ||
|
||
|
||
class Offer(models.Model): | ||
class Meta: | ||
constraints = [models.UniqueConstraint(fields=["user", "sublet"], name="unique_offer")] | ||
|
||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="offers_made") | ||
sublet = models.ForeignKey("Sublet", on_delete=models.CASCADE, related_name="offers") | ||
email = models.EmailField(max_length=255, null=True, blank=True) | ||
phone_number = PhoneNumberField(null=True, blank=True) | ||
message = models.CharField(max_length=255, blank=True) | ||
created_date = models.DateTimeField(auto_now_add=True) | ||
|
||
def __str__(self): | ||
return f"Offer for {self.sublet} made by {self.user}" | ||
|
||
|
||
class Amenity(models.Model): | ||
name = models.CharField(max_length=255, primary_key=True) | ||
|
||
def __str__(self): | ||
return self.name | ||
|
||
|
||
class Sublet(models.Model): | ||
subletter = models.ForeignKey(User, on_delete=models.CASCADE) | ||
sublettees = models.ManyToManyField( | ||
User, through=Offer, related_name="sublets_offered", blank=True | ||
) | ||
favorites = models.ManyToManyField(User, related_name="sublets_favorited", blank=True) | ||
amenities = models.ManyToManyField(Amenity, blank=True) | ||
|
||
title = models.CharField(max_length=255) | ||
address = models.CharField(max_length=255, null=True, blank=True) | ||
beds = models.IntegerField(null=True, blank=True) | ||
baths = models.IntegerField(null=True, blank=True) | ||
description = models.TextField(null=True, blank=True) | ||
external_link = models.URLField(max_length=255) | ||
min_price = models.IntegerField() | ||
max_price = models.IntegerField() | ||
created_at = models.DateTimeField(auto_now_add=True) | ||
expires_at = models.DateTimeField() | ||
start_date = models.DateField() | ||
end_date = models.DateField() | ||
|
||
def __str__(self): | ||
return f"{self.title} by {self.subletter}" | ||
|
||
|
||
class SubletImage(models.Model): | ||
sublet = models.ForeignKey(Sublet, on_delete=models.CASCADE, related_name="images") | ||
image = models.ImageField(upload_to="sublet/images") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from rest_framework import permissions | ||
|
||
|
||
class IsSuperUser(permissions.BasePermission): | ||
""" | ||
Grants permission if the current user is a superuser. | ||
""" | ||
|
||
def has_object_permission(self, request, view, obj): | ||
return request.user.is_superuser | ||
|
||
def has_permission(self, request, view): | ||
return request.user.is_superuser | ||
|
||
|
||
class SubletOwnerPermission(permissions.BasePermission): | ||
""" | ||
Custom permission to allow the owner of a Sublet to edit or delete it. | ||
""" | ||
|
||
def has_permission(self, request, view): | ||
return request.user.is_authenticated | ||
|
||
def has_object_permission(self, request, view, obj): | ||
# Check if the user is the owner of the Sublet. | ||
if request.method in permissions.SAFE_METHODS: | ||
return True | ||
return obj.subletter == request.user | ||
|
||
|
||
class OfferOwnerPermission(permissions.BasePermission): | ||
""" | ||
Custom permission to allow owner of an offer to delete it. | ||
""" | ||
|
||
def has_permission(self, request, view): | ||
return request.user.is_authenticated | ||
|
||
def has_object_permission(self, request, view, obj): | ||
if request.method in permissions.SAFE_METHODS: | ||
# Check if the user owns the sublet when getting list | ||
return obj.subletter == request.user | ||
# This is redundant, here for safety | ||
return obj.user == request.user |
Oops, something went wrong.