diff --git a/crawling.py b/crawling.py index c641710..3409264 100644 --- a/crawling.py +++ b/crawling.py @@ -1,6 +1,7 @@ # selenium의 webdriver를 사용하기 위한 import from selenium import webdriver from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys import pandas as pd @@ -11,7 +12,7 @@ driver = webdriver.Chrome() # 크롬 드라이버에 url 주소 넣고 실행 -driver.get("http://www.moamodu.com/develop/daum_map.php") +driver.get("https://map.kakao.com/") # 페이지가 완전히 로딩되도록 4초 동안 기다림 time.sleep(4) @@ -58,24 +59,42 @@ def get_lag_lng(address): return lagtitude, longitude +def get_type(restaurant_name): + search_box = driver.find_element(By.ID, "search.keyword.query") + search_box.send_keys(restaurant_name) + search_box.send_keys(Keys.RETURN) + time.sleep(3) + + try: + rtype = driver.find_element(By.CLASS_NAME, "subcategory") + type = rtype.text + except Exception: + type = "null" + + time.sleep(1) + + # 검색어 창 비우기 + search_box.clear() + + return type + + # Load the CSV file -file_path = "kakao_test.csv" +file_path = "final.csv" data = pd.read_csv(file_path) # 칼럼 추가 -data["Latitude"] = None -data["Longitude"] = None +data["Type"] = None -# 식당 주소로 위도 경도 획득 후 입력 +# 식당으로 타입 획득 후 입력 for index, row in data.iterrows(): - restaurant_address = row["Address"] - lagtitude, longitude = get_lag_lng(restaurant_address) - data.at[index, "Latitude"] = lagtitude - data.at[index, "Longitude"] = longitude + restaurant_address = row["Name"] + type = get_type(restaurant_address) + data.at[index, "Type"] = type time.sleep(1) # 데이터 저장 -data.to_csv("kakao_latlng_add.csv", encoding="utf-8-sig", index=False) +data.to_csv("restauranttype.csv", encoding="utf-8-sig", index=False) # 브라우저 닫기 driver.quit() diff --git a/friends/views.py b/friends/views.py index be52956..ea7d9c9 100644 --- a/friends/views.py +++ b/friends/views.py @@ -37,9 +37,9 @@ def friend_restaurant_list(request, id): friend_restaurants = UserRestaurantsList.objects.filter(user=friend) restaurant_ids = friend_restaurants.values_list("restaurant_id", flat=True) restaurants = Restaurant.objects.filter(id__in=restaurant_ids) - + serializer = RestaurantlistSerializer(restaurants, many=True) - + return Response({"results": serializer.data}, status=status.HTTP_200_OK) except User.DoesNotExist: return Response( diff --git a/mustgou/urls.py b/mustgou/urls.py index 354332d..c7ec8dd 100644 --- a/mustgou/urls.py +++ b/mustgou/urls.py @@ -21,5 +21,5 @@ path("admin/", admin.site.urls), path("", include("restaurants.urls")), path("auth/", include("accounts.urls")), - path("friends/", include("friends.urls")), + path("", include("friends.urls")), ] diff --git a/restaurants/migrations/0005_restaurant_food_type.py b/restaurants/migrations/0005_restaurant_food_type.py new file mode 100644 index 0000000..769417c --- /dev/null +++ b/restaurants/migrations/0005_restaurant_food_type.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.14 on 2024-08-03 07:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("restaurants", "0004_userrestaurantslist"), + ] + + operations = [ + migrations.AddField( + model_name="restaurant", + name="food_type", + field=models.CharField(blank=True, max_length=20, null=True), + ), + ] diff --git a/restaurants/migrations/0006_restaurant_image_url.py b/restaurants/migrations/0006_restaurant_image_url.py new file mode 100644 index 0000000..8bbd7a0 --- /dev/null +++ b/restaurants/migrations/0006_restaurant_image_url.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.14 on 2024-08-04 08:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("restaurants", "0005_restaurant_food_type"), + ] + + operations = [ + migrations.AddField( + model_name="restaurant", + name="image_url", + field=models.URLField(blank=True, max_length=500, null=True), + ), + ] diff --git a/restaurants/models.py b/restaurants/models.py index b06a37b..b010332 100644 --- a/restaurants/models.py +++ b/restaurants/models.py @@ -6,6 +6,7 @@ class Restaurant(models.Model): name = models.CharField(max_length=255) + food_type = models.CharField(max_length=20, null=True, blank=True) rating_naver = models.DecimalField( max_digits=5, decimal_places=2, null=True, blank=True ) @@ -18,6 +19,7 @@ class Restaurant(models.Model): address = models.CharField(max_length=255) latitude = models.DecimalField(max_digits=11, decimal_places=8) longitude = models.DecimalField(max_digits=11, decimal_places=8) + image_url = models.URLField(max_length=500, null=True, blank=True) def rating_average(self): ratings = [self.rating_naver, self.rating_kakao, self.rating_google] diff --git a/restaurants/serializers.py b/restaurants/serializers.py index 9800570..e959175 100644 --- a/restaurants/serializers.py +++ b/restaurants/serializers.py @@ -5,16 +5,14 @@ class RestaurantSerializer(serializers.ModelSerializer): - reviews = serializers.SerializerMethodField() + rating_average = serializers.SerializerMethodField() class Meta: model = Restaurant fields = "__all__" - def get_reviews(self, obj): - reviews = obj.reviews.order_by("-recommend_count")[:4] - serializer = ReviewSerializer(reviews, many=True) - return serializer.data + def get_rating_average(self, obj): + return obj.rating_average() class RestaurantListSerializer(serializers.ModelSerializer): @@ -23,7 +21,9 @@ class RestaurantListSerializer(serializers.ModelSerializer): class Meta: model = Restaurant fields = [ + "id", "name", + "food_type", "rating_average", "address", ] @@ -35,12 +35,48 @@ def get_rating_average(self, obj): class SearchHistorySerializer(serializers.ModelSerializer): class Meta: model = SearchHistory - fields = ["query", "timestamp"] + fields = ["id", "query", "timestamp"] + + +class RestaurantlistSerializer(serializers.ModelSerializer): + rating_average = serializers.SerializerMethodField() + + class Meta: + model = Restaurant + fields = [ + "id", + "name", + "food_type", + "rating_average", + "latitude", + "longitude", + "image_url", + ] + + def get_rating_average(self, obj): + return obj.rating_average() class UserRestaurantListSerializer(serializers.ModelSerializer): - restaurant = RestaurantSerializer() + restaurant = RestaurantlistSerializer() class Meta: model = UserRestaurantsList fields = "__all__" + + +class RestaurantDetailSerializer(serializers.ModelSerializer): + reviews = serializers.SerializerMethodField() + rating_average = serializers.SerializerMethodField() + + class Meta: + model = Restaurant + fields = "__all__" + + def get_reviews(self, obj): + reviews = obj.reviews.order_by("-recommend_count")[:4] + serializer = ReviewSerializer(reviews, many=True) + return serializer.data + + def get_rating_average(self, obj): + return obj.rating_average() diff --git a/restaurants/views.py b/restaurants/views.py index 2e6f8eb..61dd7f1 100644 --- a/restaurants/views.py +++ b/restaurants/views.py @@ -7,7 +7,8 @@ RestaurantSerializer, RestaurantListSerializer, SearchHistorySerializer, - UserRestaurantListSerializer, + RestaurantlistSerializer, + RestaurantDetailSerializer, ) # from django.contrib.auth.decorators import login_required @@ -25,7 +26,7 @@ def restaurant_list(request): @csrf_exempt -@api_view(["GET", "POST"]) +@api_view(["GET", "POST", "DELETE"]) # @login_required def search(request): user = User.objects.get(id=21) # 임시 유저 지정, 추후 삭제 @@ -49,6 +50,18 @@ def search(request): logging.debug("Serialized data: %s", data) return Response({"results": data}) + elif request.method == "DELETE": + history_id = request.data.get("id", "") + if not history_id: + return Response({"error": "No history ID provided"}, status=400) + + try: + history_to_delete = SearchHistory.objects.get(id=history_id, user=user) + history_to_delete.delete() + return Response({"message": "Search history deleted successfully"}) + except SearchHistory.DoesNotExist: + return Response({"error": "No matching search history found"}, status=404) + else: return Response({"error": "Unsupported method"}, status=405) @@ -57,11 +70,18 @@ def search(request): @api_view(["GET"]) # @login_required def user_restaurant_list(request): - user = User.objects.get(id=21) # 임시 유저 지정, 추후 삭제 - user_restaurants = UserRestaurantsList.objects.filter(user=user) # 추후 삭제 - # user_restaurants = UserRestaurantsList.objects.filter(user=request.user) - serializer = UserRestaurantListSerializer(user_restaurants, many=True) - return Response(serializer.data, status=status.HTTP_200_OK) + try: + user = User.objects.get(id=21) # 임시 유저 지정, 추후 삭제 + user_restaurants = UserRestaurantsList.objects.filter(user=user) # 추후 삭제 + # user_restaurants = UserRestaurantsList.objects.filter(user=request.user) + restaurant_ids = user_restaurants.values_list("restaurant_id", flat=True) + restaurants = Restaurant.objects.filter(id__in=restaurant_ids) + serializer = RestaurantlistSerializer(restaurants, many=True) + return Response({"results": serializer.data}, status=status.HTTP_200_OK) + except User.DoesNotExist: + return Response( + {"message": "Default user not found"}, status=status.HTTP_404_NOT_FOUND + ) @csrf_exempt @@ -108,7 +128,7 @@ def add_remove_restaurant(request, pk): def restaurant_detail(request, pk): try: restaurant = Restaurant.objects.prefetch_related("reviews").get(pk=pk) - serializer = RestaurantSerializer(restaurant) + serializer = RestaurantDetailSerializer(restaurant) return Response(serializer.data) except Restaurant.DoesNotExist: return Response( diff --git a/reviews/migrations/0003_alter_review_restaurant.py b/reviews/migrations/0003_alter_review_restaurant.py new file mode 100644 index 0000000..0b774ab --- /dev/null +++ b/reviews/migrations/0003_alter_review_restaurant.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.14 on 2024-08-04 11:14 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("restaurants", "0005_restaurant_food_type"), + ("reviews", "0002_alter_recommend_user_alter_review_user"), + ] + + operations = [ + migrations.AlterField( + model_name="review", + name="restaurant", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="reviews", + to="restaurants.restaurant", + ), + ), + ]